{"id":244,"date":"2024-11-07T22:44:20","date_gmt":"2024-11-07T21:44:20","guid":{"rendered":"https:\/\/extendsclass.com\/blog\/?p=244"},"modified":"2023-06-19T21:48:03","modified_gmt":"2023-06-19T19:48:03","slug":"creating-a-wordpress-plugin-a-step-by-step-guide-for-beginners","status":"publish","type":"post","link":"https:\/\/extendsclass.com\/blog\/creating-a-wordpress-plugin-a-step-by-step-guide-for-beginners","title":{"rendered":"Creating a WordPress Plugin: <br\/>A Step-by-Step Guide for Beginners"},"content":{"rendered":"\n<p>In this tutorial, we will explore the fundamentals of creating a WordPress plugin. Our plugin will be straightforward, as it will enable injecting code (JS, CSS, etc.) into the header and\/or footer (useful, among other things, for implementing Google Analytics).<\/p>\n\n\n\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_47_1 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"ez-toc-toggle-icon-1\"><label for=\"item-69e85da40c3df\" aria-label=\"Table of Content\"><span style=\"display: flex;align-items: center;width: 35px;height: 30px;justify-content: center;direction:ltr;\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/label><input  type=\"checkbox\" id=\"item-69e85da40c3df\"><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/extendsclass.com\/blog\/creating-a-wordpress-plugin-a-step-by-step-guide-for-beginners\/#Why_create_a_WordPress_plugin\" title=\"Why create a WordPress plugin?\">Why create a WordPress plugin?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/extendsclass.com\/blog\/creating-a-wordpress-plugin-a-step-by-step-guide-for-beginners\/#The_foundation_for_creating_a_plugin\" title=\"The foundation for creating a plugin\">The foundation for creating a plugin<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/extendsclass.com\/blog\/creating-a-wordpress-plugin-a-step-by-step-guide-for-beginners\/#Creating_an_Administration_Page_in_WordPress\" title=\"Creating an Administration Page in WordPress\">Creating an Administration Page in WordPress<\/a><ul class='ez-toc-list-level-3'><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/extendsclass.com\/blog\/creating-a-wordpress-plugin-a-step-by-step-guide-for-beginners\/#Creating_a_Submenu\" title=\"Creating a Submenu\">Creating a Submenu<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/extendsclass.com\/blog\/creating-a-wordpress-plugin-a-step-by-step-guide-for-beginners\/#Create_a_Configuration_View\" title=\"Create a Configuration View\">Create a Configuration View<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/extendsclass.com\/blog\/creating-a-wordpress-plugin-a-step-by-step-guide-for-beginners\/#Using_wp_head_and_wp_footer_Hooks\" title=\"Using wp_head and wp_footer Hooks\">Using wp_head and wp_footer Hooks<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/extendsclass.com\/blog\/creating-a-wordpress-plugin-a-step-by-step-guide-for-beginners\/#Conclusion\" title=\"Conclusion\">Conclusion<\/a><\/li><\/ul><\/nav><\/div>\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Why_create_a_WordPress_plugin\"><\/span>Why create a WordPress plugin?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Plugins are essential for unlocking the full potential of WordPress and extending its basic functionality.<\/p>\n\n\n\n<p>There are plugins available for almost everything! However, sometimes we may not find exactly what we need, or the desired functionality may only be available in premium versions. That&#8217;s why it can be beneficial to create a custom plugin tailored to our specific needs or even modify existing ones.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_foundation_for_creating_a_plugin\"><\/span>The foundation for creating a plugin<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p><br>A plugin can be as simple as a PHP file with the WordPress plugin header!<\/p>\n\n\n\n<p>At a minimum, the header should contain the name of the plugin:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\/**\n * Plugin Name: Basic Headers And Footers\n*\/\n?&gt;<\/code><\/pre>\n\n\n\n<p>And there you have it, with this simple file, you have created a WordPress plugin!<\/p>\n\n\n\n<p>In practice, we add a few additional fields:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/**\n * Plugin Name: Basic Headers And Footers\n * Plugin URI: https:\/\/github.com\/cyrilbois\/wp-plugin-basic-headers-and-footers\n * Description: Allows you to insert script or CSS in the header or footer.\n * Version: 1.0.0\n * Author: Cyril Bois\n * Author URI: https:\/\/github.com\/cyrilbois\n*\/<\/code><\/pre>\n\n\n\n<p>Refer to the documentation to find the comprehensive list of fields for the WordPress plugin header.<\/p>\n\n\n\n<p>Simply place this PHP file in the wp-content\/plugins folder of your WordPress installation, and it will appear in the available plugins!<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"79\" src=\"https:\/\/extendsclass.com\/blog\/wp-content\/uploads\/2023\/11\/Capture-decran-du-2023-06-19-22-11-05-1024x79.png\" alt=\"\" class=\"wp-image-249\" srcset=\"https:\/\/extendsclass.com\/blog\/wp-content\/uploads\/2023\/11\/Capture-decran-du-2023-06-19-22-11-05-1024x79.png 1024w, https:\/\/extendsclass.com\/blog\/wp-content\/uploads\/2023\/11\/Capture-decran-du-2023-06-19-22-11-05-300x23.png 300w, https:\/\/extendsclass.com\/blog\/wp-content\/uploads\/2023\/11\/Capture-decran-du-2023-06-19-22-11-05-768x59.png 768w, https:\/\/extendsclass.com\/blog\/wp-content\/uploads\/2023\/11\/Capture-decran-du-2023-06-19-22-11-05-816x63.png 816w, https:\/\/extendsclass.com\/blog\/wp-content\/uploads\/2023\/11\/Capture-decran-du-2023-06-19-22-11-05.png 1306w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Well, it&#8217;s true, for now, our plugin doesn&#8217;t do much\u2026 in fact, it does nothing!<\/p>\n\n\n\n<p>In practice, we create a folder to house our plugin because it&#8217;s rare for a plugin to be limited to just one PHP file. In our case, we&#8217;ll create a folder called <code>\/basic-headers-and-footers\/<\/code> and place our PHP file <code>basic-headers-and-footers.php<\/code> inside it. Note: The name of the PHP file is not important; it&#8217;s the WordPress header that indicates the main file of our plugin.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Creating_an_Administration_Page_in_WordPress\"><\/span>Creating an Administration Page in WordPress<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>We will create a configuration page in the WordPress dashboard to input the headers and footers to be injected.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Creating_a_Submenu\"><\/span>Creating a Submenu<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Before creating the view, we need to add an entry in the menu to make our configuration page accessible. We will add a submenu under the &#8220;Settings&#8221; menu:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"323\" height=\"385\" src=\"https:\/\/extendsclass.com\/blog\/wp-content\/uploads\/2023\/11\/wordpress-plugin-menu.png\" alt=\"\" class=\"wp-image-252\" srcset=\"https:\/\/extendsclass.com\/blog\/wp-content\/uploads\/2023\/11\/wordpress-plugin-menu.png 323w, https:\/\/extendsclass.com\/blog\/wp-content\/uploads\/2023\/11\/wordpress-plugin-menu-252x300.png 252w\" sizes=\"(max-width: 323px) 100vw, 323px\" \/><\/figure>\n\n\n\n<p>To achieve this, we need to utilize the WordPress &#8220;Hooks&#8221; system. This allows us to intercept certain actions in WordPress. We can execute custom code (action hooks) or modify values (filter hooks).<\/p>\n\n\n\n<p>We will use the &#8220;add_action&#8221; function to intercept the creation of the administration menu:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>add_action('admin_menu', 'adminMenu');<\/code><\/pre>\n\n\n\n<p>The &#8220;admin_menu&#8221; hook allows us to customize the WordPress dashboard menu.<\/p>\n\n\n\n<p>The adminMenu function will be executed when the administration menu is created.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>function adminMenu() {\n\t\/\/ The \"add_submenu_page\" function is used to create a submenu\n\tadd_submenu_page( 'options-general.php', \/\/ Specify where to place our submenu\n\t\t'Basic headers and footers', \/\/ Title of our configuration page\n\t\t'Basic headers and footers', \/\/ Label of our submenu\n\t\t'manage_options', \/\/ Required capabilities to display our submenu\n\t\t'basic-headers-and-footers', \/\/ Unique identifier for our submenu\n\t\t'adminPanel' \/\/ Function executed to generate our configuration page\n\t);\n}<\/code><\/pre>\n\n\n\n<p>And there you have it, we have already added a submenu!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Create_a_Configuration_View\"><\/span>Create a Configuration View<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Now that we have added a submenu, we can create our configuration page. This page should allow us to view and modify the headers\/footers to be injected.<\/p>\n\n\n\n<p>We will put our view in a dedicated PHP file, <code>\/views\/panel.php<\/code>, to facilitate the maintenance of our plugin. In our main PHP file, we simply need to include it to display our view:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>include_once( plugin_dir_path( __FILE__ ) . '\/views\/panel.php');<\/code><\/pre>\n\n\n\n<p>In our configuration page, we add a title and create two tabs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!-- Title of our page --&gt;\n&lt;h2&gt;Basic Headers and Footers &amp;gt; Settings&lt;\/h2&gt;\n\n&lt;!-- Our two tabs --&gt;\n&lt;div class=\"tab-menu\"&gt;\n    &lt;ul class=\"wpcr_nav_tabs\"&gt;\n        &lt;li&gt;&lt;a href=\"#\" class=\"tab-a active-a\" data-id=\"tab-header\"&gt;Header&lt;\/a&gt;&lt;\/li&gt;\n        &lt;li&gt;&lt;a href=\"#\" class=\"tab-a\" data-id=\"tab-footer\"&gt;Footer&lt;\/a&gt;&lt;\/li&gt;\n    &lt;\/ul&gt;\n&lt;\/div&gt;\n\n&lt;div class=\"tab tab-active\" data-id=\"tab-header\"&gt;\n    &lt;!-- Content of the Header tab --&gt;                  \n&lt;\/div&gt;\n&lt;div class=\"tab\" data-id=\"tab-footer\"&gt;\n    &lt;!-- Content of the Footer tab --&gt;                  \n&lt;\/div&gt;<\/code><\/pre>\n\n\n\n<p>Here is the progress we have made so far:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"422\" height=\"106\" src=\"https:\/\/extendsclass.com\/blog\/wp-content\/uploads\/2023\/11\/wordpress-plugin-config-1.png\" alt=\"\" class=\"wp-image-253\" srcset=\"https:\/\/extendsclass.com\/blog\/wp-content\/uploads\/2023\/11\/wordpress-plugin-config-1.png 422w, https:\/\/extendsclass.com\/blog\/wp-content\/uploads\/2023\/11\/wordpress-plugin-config-1-300x75.png 300w\" sizes=\"(max-width: 422px) 100vw, 422px\" \/><\/figure>\n\n\n\n<p>Next, we will add a form to update our configuration settings:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!-- We need to specify the target plugin when submitting the form --&gt;\n&lt;form action=\"options-general.php?page=basic-headers-and-footers\" method=\"post\"&gt;\n    &lt;!-- Form content --&gt;\n\n    &lt;!-- Form submit button --&gt;\n    &lt;input name=\"submit\" type=\"submit\" value=\"Save\" class=\"button button-primary\" \/&gt;\n&lt;\/form&gt;<\/code><\/pre>\n\n\n\n<p>In the form, we will add a textarea for each option:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;textarea name=\"bhaf_header\" class=\"widefat\" rows=\"10\"&gt;&lt;\/textarea&gt;\n...\n&lt;textarea name=\"bhaf_footer\" class=\"widefat\" rows=\"10\"&gt;&lt;\/textarea&gt;<\/code><\/pre>\n\n\n\n<p>We will also add a nonce to secure our form (this will simply verify that the form submission is coming from our page):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php wp_nonce_field('basic-headers-and-footers', 'bhaf_nonce' ); ?&gt;<\/code><\/pre>\n\n\n\n<p>Now, let&#8217;s handle the configuration saving:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>function adminPanel() {\n    \/\/ Check access rights\n    if ( ! current_user_can( 'manage_options' ) ) {\n        return;\n    }\n    \/\/ If \"submit\" is set, the form has been submitted and we need to save the settings\n    if (isset($_REQUEST&#91;'submit'])) {\n        if (wp_verify_nonce($_REQUEST&#91;'bhaf_nonce'], 'basic-headers-and-footers')) {\n            \/\/ Save the header code\n            update_option('bhaf_header', stripslashes_deep($_REQUEST&#91;'bhaf_header']));\n            \/\/ Save the footer code\n            update_option('bhaf_footer', stripslashes_deep('bhaf_footer']));\n        }\n    }\n    \/\/ Display the view\n    include_once( $this-&gt;path . '\/views\/panel.php');\n}<\/code><\/pre>\n\n\n\n<p>Let&#8217;s revisit our textareas, as we need to initialize them with the existing codes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;textarea name=\"bhaf_header\" class=\"widefat\" rows=\"10\"&gt;&lt;?php echo esc_html(get_option('bhaf_header')); ?&gt;&lt;\/textarea&gt;<\/code><\/pre>\n\n\n\n<p>The <code><strong>get_option<\/strong><\/code> function returns the value of our option.<\/p>\n\n\n\n<p>Here is the final rendering of our configuration page:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"800\" height=\"422\" src=\"https:\/\/extendsclass.com\/blog\/wp-content\/uploads\/2023\/11\/wordpress-plugin-config.png\" alt=\"\" class=\"wp-image-254\" srcset=\"https:\/\/extendsclass.com\/blog\/wp-content\/uploads\/2023\/11\/wordpress-plugin-config.png 800w, https:\/\/extendsclass.com\/blog\/wp-content\/uploads\/2023\/11\/wordpress-plugin-config-300x158.png 300w, https:\/\/extendsclass.com\/blog\/wp-content\/uploads\/2023\/11\/wordpress-plugin-config-768x405.png 768w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Using_wp_head_and_wp_footer_Hooks\"><\/span>Using wp_head and wp_footer Hooks<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Now, all that&#8217;s left is to dynamically modify the header and footer of WordPress site pages based on the configured settings.<\/p>\n\n\n\n<p>For this purpose, we will utilize the wp_head and wp_footer Hooks.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Hook for the header\nadd_action('wp_head', 'injectHeader');\n\n\/\/ Hook for the footer\nadd_action('wp_footer', 'injectFooter');\n\nfunction injectHeader() {\n    inject('bhaf_header');\n}\n\nfunction injectFooter() {\n    inject('bhaf_footer');\n}\n\nfunction inject($section) {\n    \/\/ Do not inject code on certain pages (such as robots.txt ...)\n    if (is_admin() || is_feed() || is_robots() || is_trackback()) {\n        return;\n    }\n    \/\/ Get the configured code\n    $data = get_option($section);\n    if (!empty($data)) {\n        \/\/ Inject the code into the header\/footer\n        echo $data;\n    }\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The process of creating a WordPress plugin is straightforward and allows you to quickly create exciting functionalities.<\/p>\n\n\n\n<p>In this tutorial, we have only covered a small portion of the possibilities offered by WordPress. I will write future articles on other features.<\/p>\n\n\n\n<p>To enhance your skills, one effective technique is to examine and modify the code of existing extensions. It is recommended to start with plugins that have limited functionalities, as it allows you to quickly and easily review the relevant code.<\/p>\n\n\n\n<p>For further exploration:<\/p>\n\n\n\n<ul>\n<li><a href=\"https:\/\/developer.wordpress.org\/plugins\/plugin-basics\/\" title=\"\">Official WordPress plugin creation documentation<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/cyrilbois\/wp-plugin-basic-headers-and-footers\" title=\"\">Source code of this tutorial<\/a><\/li>\n<\/ul>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial, we will explore the fundamentals of creating a WordPress plugin. Our plugin will be straightforward, as it will enable injecting code (JS, CSS, etc.) into the header and\/or footer (useful, among other things, for implementing Google Analytics).<\/p>\n","protected":false},"author":1,"featured_media":256,"comment_status":"open","ping_status":"open","sticky":true,"template":"","format":"standard","meta":{"_sitemap_exclude":false,"_sitemap_priority":"","_sitemap_frequency":""},"categories":[2],"tags":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/extendsclass.com\/blog\/wp-json\/wp\/v2\/posts\/244"}],"collection":[{"href":"https:\/\/extendsclass.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/extendsclass.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/extendsclass.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/extendsclass.com\/blog\/wp-json\/wp\/v2\/comments?post=244"}],"version-history":[{"count":10,"href":"https:\/\/extendsclass.com\/blog\/wp-json\/wp\/v2\/posts\/244\/revisions"}],"predecessor-version":[{"id":246,"href":"https:\/\/extendsclass.com\/blog\/wp-json\/wp\/v2\/posts\/244\/revisions\/246"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/extendsclass.com\/blog\/wp-json\/wp\/v2\/media\/256"}],"wp:attachment":[{"href":"https:\/\/extendsclass.com\/blog\/wp-json\/wp\/v2\/media?parent=244"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/extendsclass.com\/blog\/wp-json\/wp\/v2\/categories?post=244"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/extendsclass.com\/blog\/wp-json\/wp\/v2\/tags?post=244"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}