In this tutorial, we will dive into the development of a Custom WordPress Plugin using the PHP language. The primary goal is to provide students and beginners, particularly those new to WordPress and PHP, with a reference to learning useful techniques to enhance their knowledge and programming capabilities. I'll be offering sample snippets and a sample WordPress plugin source code that demonstrates our main goal in this tutorial.
WordPress is a widely utilized open-source content management system (CMS) that enables users to create and manage websites and blogs. It is written in PHP and employs a MySQL or MariaDB database. WordPress has evolved from its origins as a blogging platform to a versatile CMS utilized by individuals, businesses, and organizations for various types of websites, including blogs, portfolios, e-commerce sites, and corporate websites.
A WordPress plugin is a software component that extends and enhances the functionality of a WordPress website. Plugins are pivotal in making WordPress a flexible and customizable content management system (CMS). They enable users to incorporate specific features or capabilities into their websites without modifying the core WordPress code.
To create a Custom WordPress Plugin, make a new directory in your WordPress website within the `source_code_path>wp-contents>plugins` folder. Then, create a new PHP file.
Open your newly created PHP file with your preferred code editor, such as MS VS Code, Sublime, or Notepad++.
Next, we need to provide the Plugin's information header at the top line of the PHP file. The information header is enclosed in comment tags. Below is an example information header for a sample WordPress Plugin:
<?php /** * Plugin Name: My Custom Plugin Name * Plugin URI: URI of your plugin where your docs, updates, or etc located * Description: A brief description of yout plugin * Version: your plugin version * Author: the plugins author name * Author URI: the plugins author URI * License: license name e.g. GPL2 */ ?>
After completing these steps, you will be able to locate your Custom WordPress Plugin on the Plugins Page of your WordPress admin side.
For a more better understanding of creating a Custom WordPress Plugin, I have developed a simple plugin that includes CRUD (Create, Read, Update, and Delete) features on the admin side. The provided plugin script also involves the creation of a new database table.
Below is the PHP script for the simple plugin I created:
<?php /** * Plugin Name: My First Custom Plugin * Plugin URI: https://sample-domain.com * Description: Lorem ipsum dolor sit amet consectetur adipisicing elit. * Version: 1.0 * Author: oretnom23 * Author URI: https://www.sourcecodester.com/user/257130/activity * License: GPLv2 or later */ die; } class MyFirstPlugin{ public $notices = []; function __construct() { add_action( 'admin_menu', [ $this, 'pages' ] ); add_action( 'admin_enqueue_scripts', [$this, 'bootstrap_scripts'], 10, 1 ); // Process Form add_action( 'admin_init', [ $this, 'save_form' ] ); add_action( 'admin_init', [ $this, 'delete_mfcp' ] ); // print_r(gettype($this->notices));exit; add_action( 'admin_notices', [$this, 'display_notices'] ); } function pages(){ //add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position ); add_menu_page(__('My First Custom Plugin'), __('Custom Plugin'), 'administrator', 'my-first-custom-plugin-page', [$this, 'my_plugin_list_page'], '', 25); add_submenu_page('my-first-custom-plugin-page', __('Manage Plugin\'s DB'), __('Add New'), 'administrator', 'my-first-custom-plugin-page-form', [$this, 'my_plugin_form_page']); } function display_notices(){ // print_r($this->notices);exit; foreach($this->notices as $k =>$notice){ ?> <div class="notice notice-<?= $notice['type'] ?> <?= ($notice['dismissible']) ? "is-dismissible" : "" ?>"> </div> <?php } } update_option("mfcp_notices", []); } function activate(){ // Install Plugin's Database $this->install_db(); } function deactivate(){ } function uninstall(){ } /** * Enqueue Styles and Scripts */ function bootstrap_scripts($hook){ // Enqueue Bootstrap CDN CSS and JS only in plugin's page if($hook == 'toplevel_page_my-first-custom-plugin-page' || $hook == 'custom-plugin_page_my-first-custom-plugin-page-form'){ wp_enqueue_style("fontawesome-icon-cdn","https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css",[],"6.1.2", "all"); wp_enqueue_style("bootstrap-css-cdn","https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css",[],"5.3.2", "all"); wp_enqueue_script("fontawesome-icon-js-cdn","https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/js/all.min.js",[],"6.1.2", "all"); wp_enqueue_script("bootstrap-js-cdn","https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js",[],"5.3.2", "all"); } // echo $hook;exit; } /** * Create Plugin's Database */ function install_db(){ global $wpdb; $table = $wpdb->prefix."mfp_tbl"; $qry = $wpdb->prepare("SHOW TABLES LIKE %s", $wpdb->esc_like($table)); if($wpdb->get_var($qry) == $table){ /** * Table Already Exists */ }else{ /** * Table Doesn't Exists on the Database * - Install Table */ $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE IF NOT EXISTS $table ( `id` int(30) NOT NULL PRIMARY KEY AUTO_INCREMENT, `meta_field` text DEFAULT NULL, `meta_value` text DEFAULT NULL, `created_at` datetime NOT NULL DEFAULT current_timestamp(), `updated_at` datetime DEFAULT NULL ON UPDATE current_timestamp() ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); } } /** * Create Plugin's Form Page */ function my_plugin_form_page(){ global $wpdb; $data = $wpdb->get_row( $wpdb->prepare("SELECT * FROM `{$wpdb->prefix}mfp_tbl` where `id` = %d", [$_GET['mfcp_id']]), ARRAY_A ); } ?> <style> .card{ max-width: unset !important; } </style> <div class="container-fluid"> <div class="card shadow col-lg-5 col-md-8 col-sm-12 col-12 mx-auto p-0"> <div class="card-header rounded-0"> <div class="card-title">Plugin's Sample Form <?= (!empty($mfcp_id ?? "")? " - Updating #{$mfcp_id}" : "") ?></div> </div> <div class="card-body"> <div class="container-fluid"> <form action="" id="sample-form" method="POST"> <?php wp_nonce_field( "mfcp-sample-form" ); ?> <input type="hidden" name="action" value="save-mfcp-sample-form"> <input type="hidden" name="id" value="<?= $mfcp_id ?? "" ?>"> <div class="mb-3"> <label for="meta_field" class="form-label">Meta Field <small class="text-danger">*</small></label> <input type="text" class="form-control rounded-0" id="meta_field" name="meta_field" value="<?= $_POST['meta_field'] ?? $mfcp_meta_field ?? "" ?>" required="required" autofocus> </div> <div class="mb-3"> <label for="meta_value" class="form-label">Meta Value <small class="text-danger">*</small></label> <textarea name="meta_value" id="meta_value" rows="3" class="form-control rounded-0" requried=""><?= $_POST['meta_value'] ?? $mfcp_meta_value ?? "" ?></textarea> </div> <div class="mb-3"> <button class="btn btn-primary rounded-0" type="submit">Save</button> </div> </form> </div> </div> </div> </div> <? } /** * Create Plugin's List Page */ function my_plugin_list_page(){ global $wpdb; $data = $wpdb->get_results( $wpdb->prepare(" SELECT * FROM `{$wpdb->prefix}mfp_tbl` order by id ASC "), ARRAY_A ); ?> <style> .card{ max-width: unset !important; } </style> <div class="container-fluid"> <div class="card shadow col-12 p-0"> <div class="card-header rounded-0"> <div class="card-title">Plugin's Database Data</div> </div> <div class="card-body"> <div class="container-fluid"> <div class="table-responsive"> <table class="table table-striped table-hover table-bordered"> <colgroup> <col width="20%"> <col width="30%"> <col width="30%"> <col width="20%"> </colgroup> <thead> <tr> <th class="text-center px-2 py-1 text-light bg-primary">Date Added</th> <th class="text-center px-2 py-1 text-light bg-primary">Meta Field</th> <th class="text-center px-2 py-1 text-light bg-primary">Meta Value</th> <th class="text-center px-2 py-1 text-light bg-primary">Action</th> </tr> </thead> <tbody> <?php foreach($data as $row): ?> <tr> <td class="px-2 py-1"><?= $row['meta_field'] ?></td> <td class="px-2 py-1"><?= $row['meta_value'] ?></td> <td class="px-2 py-1"> <div class="input-group d-flex justify-content-center"> <a href="<?= admin_url("admin.php?page=my-first-custom-plugin-page-form&mfcp_id={$row['id']}") ?>" class="btn btn-sm btn-outline-primary rounded-0" title="Edit"><i class="fa fa-edit"></i></a> <a href="<?= admin_url("admin.php?page=my-first-custom-plugin-page-form&action=delete_mfcp&mfcp_id={$row['id']}") ?>" class="btn btn-sm btn-outline-danger rounded-0 delete-mfcp" title="Delete"><i class="fa fa-trash"></i></a> </div> </td> </tr> <?php endforeach; ?> <?php else: ?> <tr> <th class="text-center px-2 py-1" colspan="4">No Data Found!</th> </tr> <?php endif; ?> </tbody> </table> </div> </div> </div> </div> </div> <script> var delete_mfcp = document.querySelectorAll('.delete-mfcp') delete_mfcp.forEach(el=>{ el.addEventListener('click', function(e){ if(confirm(`Are you sure to delete this data?`) === false) e.preventDefault(); }) }) </script> <? } /** * Save Form Data */ function save_form(){ global $wpdb; $resp=[]; if( $_POST['action'] == 'save-mfcp-sample-form' ){ if(!wp_verify_nonce( $mfcp__wpnonce, 'mfcp-sample-form')){ $resp = ["type" => "danger", "message" => "Security Check Failed!"]; }else{ $mfcp_meta_field = sanitize_text_field( $mfcp_meta_field ); $mfcp_meta_value = sanitize_textarea_field( $mfcp_meta_value ); $save = $wpdb->insert( "{$wpdb->prefix}mfp_tbl", [ "meta_field" => $mfcp_meta_field, "meta_value" => $mfcp_meta_value ], [ '%s', '%s' ] ); }else{ $save = $wpdb->update("{$wpdb->prefix}mfp_tbl", [ "meta_field" => $mfcp_meta_field, "meta_value" => $mfcp_meta_value ], [ "id" => $mfcp_id, ], [ '%s', '%s' ], [ '%d', ] ); } if($wpdb->last_error){ $resp = ["type" => "danger", "message" => $wpdb->last_error]; }else{ $resp = ["type" => "success", "message" => "Data has been saved successfully!"]; } } $this->notices[] = $resp; update_option("mfcp_notices", $this->notices); echo "<script>location.replace(`".admin_url("admin.php?page=my-first-custom-plugin-page")."`)</script>"; exit; } } /** * Delete Data */ function delete_mfcp(){ global $wpdb; if( $_GET['page'] == 'my-first-custom-plugin-page-form' && $_GET['action'] == 'delete_mfcp'&& ){ $delete = $wpdb->delete("{$wpdb->prefix}mfp_tbl", [ "id" => $_GET['mfcp_id']], ['%d']); if($wpdb->last_error){ $resp = ["type" => "danger", "message" => $wpdb->last_error]; }else{ $resp = ["type" => "success", "message" => "Data has been deleted successfully!"]; } $this->notices[] = $resp; update_option("mfcp_notices", $this->notices); echo "<script>location.replace(document.referrer)</script>"; exit; } } } $MyFirstPlugin = new MyFirstPlugin(); }
Explore the snapshots below, capturing the results of the Custom WordPress Plugin Script provided above:
And there you have it! I trust this Custom WordPress Plugin Guide proves helpful for your needs and becomes a valuable resource for your current and future WordPress projects.
Consider exploring the following topics as well:
Explore more into this website for an array of Tutorials, Free Source Codes, and Articles spanning various programming languages.