Need Plugin in WordPress? As a WordPress developer, I have created many plugins and learned a lot about how to create a simple one from scratch. In this article, I will share with you the steps I follow to create a simple plugin that includes a menu item called “Test Plugin”, a database table, and three pages for displaying, adding, and editing data.

Create the main plugin file:

The first step is to create the main plugin file. In this case, we’ll call it “test-plugin.php”. This file will contain the information about the plugin, including the plugin name, version, and description. Additionally, it will be responsible for activating and deactivating the plugin, creating the database table, and displaying the main page of the plugin in the WordPress admin panel.

Add the plugin header:

At the top of the main plugin file, we need to add the plugin header, which will contain the information about the plugin. This information will be used by WordPress to display the plugin in the plugins list.

/*
  Plugin Name: Test Plugin
  Plugin URI: https://example.com/test-plugin
  Description: A simple plugin for demonstration purposes
  Version: 1.0
  Author: Sozonenko Anton
  Author URI: https://sozon-dev.com.ua/
*/

Register the activation and deactivation hooks:

Next, we need to register the activation and deactivation hooks, which will be triggered when the plugin is activated or deactivated. In the activation hook, we’ll create the database table, and in the deactivation hook, we’ll drop the table.

register_activation_hook( __FILE__, 'test_plugin_activate' );
function test_plugin_activate() {
  //Code to create the database table
}

register_deactivation_hook( __FILE__, 'test_plugin_deactivate' );
function test_plugin_deactivate() {
  //Code to drop the database table
}

Add a menu item:

To add a menu item, we need to use the add_menu_page function, which will create a top-level menu item in the WordPress admin panel. In this case, the menu item will be called “Test Plugin”.

add_menu_page( 'Test Plugin', 'Test Plugin', 'manage_options', 'test-plugin', 'test_plugin_display_main_page' );
function test_plugin_display_main_page() {
  //Code to display the main plugin page
}

Create the database table:

In the activation hook, we’ll create the database table using the dbDelta function. This function will create the table if it doesn’t exist and will alter it if the structure has changed.

function test_plugin_activate() {
  global $wpdb;
  $table_name = $wpdb->prefix . 'test_plugin';
  $charset_collate = $wpdb->get_charset_collate();
  $sql = "CREATE TABLE $table_name (
    id mediumint(9) NOT NULL AUTO_INCREMENT,
    time datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
    name tinytext NOT NULL,
    text text NOT NULL,
    url varchar(55) DEFAULT '' NOT NULL,
    PRIMARY KEY  (id)
  ) $charset_collate;";
    require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
    dbDelta( $sql );
}

Create the display, add, and edit pages:

We’ll create three separate PHP files for the display, add, and edit pages.

  • `test-list.php` will be responsible for displaying the entries from the database.
  • `test-add-data.php` will be responsible for adding a record to the table.
  • `test-edit-data.php` will be responsible for editing a record in the table.

Include the display add, and edit pages:

In the main plugin file, we’ll include these three files, which will be used to display, add, and edit data.

function test_plugin_display_main_page() {
  include( plugin_dir_path( FILE ) . 'test-list.php' );
}

add_action( 'admin_post_test_plugin_add_data', 'test_plugin_add_data' );
function test_plugin_add_data() {
  include( plugin_dir_path( FILE ) . 'test-add-data.php' );
}

add_action( 'admin_post_test_plugin_edit_data', 'test_plugin_edit_data' );
function test_plugin_edit_data() {
  include( plugin_dir_path( FILE ) . 'test-edit-data.php' );
}

Here’s the file structure for the WordPress plugin:

test-plugin/
  ├── test-add-data.php
  ├── test-edit-data.php
  ├── test-list.php
  └── test-plugin.php

Next, I will show you an example of the finished code for each file:

– test-plugin.php

/*
  Plugin Name: Test Plugin
  Plugin URI: http://example.com/test-plugin
  Description: A simple plugin for testing purposes
  Version: 1.0
  Author: Your Name
  Author URI: http://example.com
*/

//Exit if accessed directly
if ( !defined( 'ABSPATH' ) ) exit;

register_activation_hook( __FILE__, 'test_plugin_create_db' );
function test_plugin_create_db() {
  global $wpdb;
  $table_name = $wpdb->prefix . 'test_plugin';
  $sql = "CREATE TABLE $table_name (
    id int(11) NOT NULL AUTO_INCREMENT,
    name varchar(255) NOT NULL,
    email varchar(255) NOT NULL,
    PRIMARY KEY (id)
  ) COLLATE utf8mb4_general_ci;";
  require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
  dbDelta( $sql );
}

add_action( 'admin_menu', 'test_plugin_menu_item' );
function test_plugin_menu_item() {
  add_menu_page(
    'Test Plugin',
    'Test Plugin',
    'manage_options',
    'test-plugin',
    'test_plugin_display_main_page',
    'dashicons-admin-generic',
    6
  );
}

function test_plugin_display_main_page() {
  include( plugin_dir_path( __FILE__ ) . 'test-list.php' );
}

add_action( 'admin_post_test_plugin_add_data', 'test_plugin_add_data' );
function test_plugin_add_data() {
  include( plugin_dir_path( __FILE__ ) . 'test-add-data.php' );
}

add_action( 'admin_post_test_plugin_edit_data', 'test_plugin_edit_data' );
function test_plugin_edit_data() {
  include( plugin_dir_path( __FILE__ ) . 'test-edit-data.php' );
}

– test-list.php

<?php
  global $wpdb;
  $table_name = $wpdb->prefix . 'test_plugin';
  $data = $wpdb->get_results( "SELECT * FROM $table_name" );
?>

<div class="wrap">
  <h1>Test Plugin</h1>
  <table class="wp-list-table widefat fixed striped posts">
    <thead>
      <tr>
        <th>ID</th>
        <th>Name</th>
        <th>Email</th>
        <th>Actions</th>
      </tr>
    </thead>
    <tbody>
    <?php foreach ( $data as $d ): ?>
      <tr>
        <td><?php echo $d->id; ?></td>
        <td><?php echo $d->name; ?></td>
        <td><?php echo $d->email; ?></td>
        <td>
          <a href="<?php echo admin_url( 'admin-post.php?action=test_plugin_edit_data&id=' . $d->id ); ?>">Edit</a>
          |
          <a href="<?php echo wp_nonce_url( admin_url( 'admin-post.php?action=test_plugin_delete_data&id=' . $d->id ), 'test_plugin_delete_data_' . $d->id, '_wpnonce' ); ?>">Delete</a>
        </td>
      </tr>
    <?php endforeach; ?>
    </tbody>
  </table>
  <h2>Add Data</h2>
  <form action="<?php echo admin_url( 'admin-post.php' ); ?>" method="post">
    <input type="hidden" name="action" value="test_plugin_add_data">
    <table class="form-table">
      <tbody>
        <tr>
          <th>
            <label for="test_plugin_name">Name</label>
          </th>
          <td>
            <input type="text" id="test_plugin_name" name="test_plugin_name" class="regular-text">
          </td>
        </tr>
        <tr>
          <th>
            <label for="test_plugin_email">Email</label>
          </th>
          <td>
            <input type="email" id="test_plugin_email" name="test_plugin_email" class="regular-text">
          </td>
        </tr>
      </tbody>
    </table>
    <?php submit_button( 'Add Data' ); ?>
  </form>
</div>

– test-add-data.php

global $wpdb;
$table_name = $wpdb->prefix . 'test_plugin';
$wpdb->insert(
  $table_name,
  array(
    'name' => $_POST['test_plugin_name'],
    'email' => $_POST['test_plugin_email'],
  )
);
wp_redirect( admin_url( 'admin.php?page=test-plugin' ) );
exit;

– test-edit-data.php

global $wpdb;
$table_name = $wpdb->prefix . 'test_plugin';
$data = $wpdb->get_row( "SELECT * FROM $table_name WHERE id = " . $_GET['id'] );
?>
<div class="wrap">
  <h2>Edit Data</h2>
  <form action="<?php echo admin_url( 'admin-post.php' ); ?>" method="post">
    <input type="hidden" name="action" value="test_plugin_update_data">
    <input type="hidden" name="id" value="<?php echo $data->id; ?>">
    <table class="form-table">
      <tbody>
        <tr>
          <th>
            <label for="test_plugin_name">Name</label>
          </th>
          <td>
            <input type="text" id="test_plugin_name" name="test_plugin_name" class="regular-text" value="<?php echo $data->name; ?>">
          </td>
        </tr>
        <tr>
          <th>
            <label for="test_plugin_email">Email</label>
          </th>
          <td>
            <input type="email" id="test_plugin_email" name="test_plugin_email" class="regular-text" value="<?php echo $data->email; ?>">
          </td>
        </tr>
      </tbody>
    </table>
    <?php submit_button( 'Update Data' ); ?>
  </form>
</div>

– test-update-data.php

global $wpdb;
$table_name = $wpdb->prefix . 'test_plugin';
$wpdb->update(
  $table_name,
  array(
    'name' => $_POST['test_plugin_name'],
    'email' => $_POST['test_plugin_email'],
  ),
  array( 'id' => $_POST['id'] ),
  array(
    '%s',
    '%s'
  ),
  array( '%d' )
);
wp_redirect( admin_url( 'admin.php?page=test-plugin' ) );
exit;

Finally, to activate the plugin, you just need to include the main plugin file test-plugin.php in your WordPress installation by uploading it to the wp-content/plugins directory and then activating it from the WordPress admin panel.

With this basic setup, you have created a simple WordPress plugin that has a menu item in the WordPress admin panel, displays data from a database table, and allows you to add, edit, and update data. Of course, you can build upon this foundation to create more complex plugins.

I hope this helps you get started with creating your own WordPress plugins!

More information can be found in the documentation

Thank you very much for visiting. Goodbye!