{"id":15355,"date":"2023-02-22T12:22:46","date_gmt":"2023-02-22T10:22:46","guid":{"rendered":"https:\/\/web-mate.gr\/how-to-build-a-wordpress-plugin\/"},"modified":"2026-10-29T13:37:25","modified_gmt":"2026-10-29T11:37:25","slug":"how-to-build-a-wordpress-plugin","status":"publish","type":"post","link":"https:\/\/web-mate.gr\/en\/how-to-build-a-wordpress-plugin\/","title":{"rendered":"How to Build a WordPress Plugin"},"content":{"rendered":"<p>No one can argue that WordPress hasn&#8217;t changed the world of CMS platforms on the internet: it is currently the most widely used CMS, and the fact that it is open source strengthens its position even further for years to come! Let&#8217;s not forget another point either: WordPress started out as a blogging platform and has since expanded its capabilities to building web apps!<\/p>\n<p><a href=\"https:\/\/web-mate.gr\/wp-content\/uploads\/2023\/02\/wordpress-mug1.jpg\"><img decoding=\"async\" class=\"aligncenter wp-image-584 size-full\" title=\"wordpress plugin\" src=\"https:\/\/web-mate.gr\/wp-content\/uploads\/2023\/02\/wordpress-mug1.jpg\" alt=\"wordpress plugin\" width=\"455\" height=\"304\" \/><\/a><\/p>\n<p>The basics you need before creating any WordPress plugin are a knowledge of\u00a0<a href=\"http:\/\/www.w3schools.com\/php\/default.asp\" target=\"_blank\" rel=\"external noopener noreferrer\">PHP<\/a>\u00a0and an understanding of the\u00a0\u00a0<a href=\"http:\/\/codex.wordpress.org\/Site_Architecture_1.5\" target=\"_blank\" rel=\"external noopener noreferrer\">WordPress file structure<\/a>\u00a0and the <a href=\"http:\/\/codex.wordpress.org\/Administration_Panels\" target=\"_blank\" rel=\"external noopener noreferrer\">Administration panel<\/a>.<\/p>\n<p>But why would anyone develop a plugin? Quite simply, because it&#8217;s relatively easy, and because if you ask someone else to build it they will charge you a lot of money, and afterwards you won&#8217;t be able to customise it easily yourself!<\/p>\n<h4>Folder structure for a WordPress plugin<\/h4>\n<p><a href=\"https:\/\/web-mate.gr\/wp-content\/uploads\/2023\/02\/wordpress-install-dir-plugins.jpg\"><img decoding=\"async\" class=\"aligncenter wp-image-585 size-full\" title=\"wordpress-install-dir-plugins\" src=\"https:\/\/web-mate.gr\/wp-content\/uploads\/2023\/02\/wordpress-install-dir-plugins.jpg\" alt=\"wordpress-install-dir-plugins\" width=\"550\" height=\"250\" \/><\/a><\/p>\n<p>As the image shows, this is usually what the folders look like in a WordPress installation. If we want to create a small plugin made up of a single file, we can place it directly in the plugins folder without putting it inside a folder of its own. For larger plugins we create a new folder inside the plugins folder and put the plugin&#8217;s files there. If we want to share the plugin for download, we can, and should, create a readme.txt file with information such as the plugin&#8217;s name and what it does! Finally, we can add information about any updates made to the plugin.<\/p>\n<h4>Starting the plugin<\/h4>\n<p>When we start a plugin, we need to create a PHP file with any name we like (ideally one that describes what the plugin does). In our example it will be called excerpt.php.<\/p>\n<p>The first lines of the plugin must be comments that WordPress can read. If they are missing, the plugin will not work. Below is the format these comments should have<br \/>\n<code><br \/>\n<\/code><\/p>\n<ol start=\"1\">\n<li>&lt;?php<\/li>\n<li>\/*<\/li>\n<li>Plugin\u00a0Name:\u00a0Plugin\u00a0Name\u00a0here<\/li>\n<li>Plugin\u00a0URI:\u00a0http:\/\/www.yourpluginurlhere.com\/<\/li>\n<li>Version:\u00a0Current\u00a0Version<\/li>\n<li>Author:\u00a0Name\u00a0please<\/li>\n<li>Description:\u00a0What\u00a0does\u00a0your\u00a0plugin\u00a0do\u00a0and\u00a0what\u00a0features\u00a0does\u00a0it\u00a0offer&#8230;<\/li>\n<li>*\/<\/li>\n<li>?&gt;<\/li>\n<\/ol>\n<p>The Plugin Name is what will appear in the WordPress admin panel, and the same goes for the URI, which will appear in the details. It&#8217;s also a good idea to include the plugin&#8217;s version, which makes it look more professional!<\/p>\n<h4>Techniques for building a WordPress plugin<\/h4>\n<p>There are several well-known ways to build your plugin. Most of the time, &#8220;experienced&#8221; developers create a class so they don&#8217;t run into problems with function and variable names. If you&#8217;re not familiar with PHP&#8217;s OOP model, though, you&#8217;re better off writing your code as plain functions.<\/p>\n<p>So for our example we&#8217;ll write a simple function to save our data. Below is a snippet of the plugin&#8217;s code.<\/p>\n<ol start=\"1\">\n<li>?php<\/li>\n<li>define(&#8220;exampleVariable&#8221;,\u00a0&#8220;this\u00a0is\u00a0a\u00a0value&#8221;);<\/li>\n<li>function jim_content_example_function(\u00a0$limit\u00a0)\u00a0{<\/li>\n<li>\u00a0\u00a0\/\/\u00a0some\u00a0code\u00a0goes\u00a0here<\/li>\n<li>}<\/li>\n<li>?&gt;<\/li>\n<\/ol>\n<p>In our example we use jim as the prefix. You can replace it with anything you like (usually something related to the plugin&#8217;s name). Of course, the snippet above is more of a template than real code!<\/p>\n<h4>WordPress Filters And Actions<\/h4>\n<p>Filters and actions are an essential part of building a plugin. With them we can update content or add an extra option. A proper understanding of them, combined with a knowledge of the WordPress API, can lead to amazing results!<\/p>\n<h4>Add_filter()<\/h4>\n<p>A filter is used when a piece of data or text passes through WordPress. With filters you can fairly easily filter content through your own functions in any way you like.<\/p>\n<p>To make this a bit clearer: with a filter you can change $the_content or wp_title, which WordPress uses, and give them whatever form you want, e.g. make the title have two images of your choice on its left and right, or two span tags for styling purposes!<\/p>\n<p>Filters are usually used to format text, as in the example above. The title example could look like this<\/p>\n<ol start=\"1\">\n<li>add_filter(&#8216;wp_title&#8217;,\u00a0&#8216;jim_func&#8217;);<\/li>\n<\/ol>\n<p>Here we use a filter to change the title (this example isn&#8217;t related to the plugin in our example).<\/p>\n<p>add_filter is a built-in WordPress function and is used to add a new filter to the content. In the example above we target $wp_title, which holds the title of our page. We then pass this variable to a function called jim_func(), which can output the title however we want, for any purpose.<\/p>\n<h4>Add_action()<\/h4>\n<p>Actions are similar to filters, but instead of working with variables, text and so on, they work with predefined points in the templates and the admin panel. For example, you could add an action that runs when the content of a page is updated or changed. WordPress offers\u00a0<a href=\"http:\/\/codex.wordpress.org\/Plugin_API\/Action_Reference\" target=\"_blank\" rel=\"external noopener noreferrer\">a useful list of actions<\/a>\u00a0in its API. Here are some examples:<\/p>\n<ul>\n<li><strong>publish_post<\/strong>\u00a0\u2013 called when a post is published or its status changes to published.<\/li>\n<li><strong>save_post<\/strong>\u00a0\u2013 called when a page\/post is created from scratch or updated<\/li>\n<li><strong>wp_head<\/strong>\u00a0\u2013 called when the template loads and runs the wp_head() function<\/li>\n<li><strong>loop_end<\/strong>\u00a0\u2013 called as soon as the loop ends<\/li>\n<\/ul>\n<p>Once again we can see how simple the logic of the code is. If you understand the difference between actions and filters, you can create amazing results! Below is another snippet that creates an action with the help of save_post, which we mentioned above.<\/p>\n<ol start=\"1\">\n<li>add_action(&#8216;save_post&#8217;,\u00a0&#8216;notify&#8217;);<\/li>\n<\/ol>\n<div><a href=\"https:\/\/web-mate.gr\/wp-content\/uploads\/2023\/02\/wp-hooks-guide.jpg\"><img decoding=\"async\" class=\"aligncenter wp-image-594 size-full\" title=\"wp-hooks\" src=\"https:\/\/web-mate.gr\/wp-content\/uploads\/2023\/02\/wp-hooks-guide.jpg\" alt=\"wp-hooks\" width=\"500\" height=\"300\" \/><\/a><\/div>\n<p>The format is similar to add_filter(). We need 2 arguments: the first holds the name of the hook we&#8217;re targeting, in our case save_post, which means that every time a post is saved, the function in the second position runs, in this case notify.<\/p>\n<h4>Creating our WordPress plugin<\/h4>\n<p>To finish, we&#8217;ll add our function to the plugin file. The WordPress API is very specific and the documentation is very good, and that&#8217;s where a developer can find answers to more specialised questions.<\/p>\n<p>The function must go right after the comments in the plugin file. Alternatively, it could go in functions.php. The function is used to generate dynamic content based on a specific number of characters.<\/p>\n<p>So for our example we can set the limit to 55 characters with the jim_trim_content() function. We could use this function in the sidebar or in the content.<\/p>\n<ol start=\"1\">\n<li>&lt;?php<\/li>\n<li>function\u00a0jim_content(\u00a0$limit\u00a0)\u00a0{<\/li>\n<li>\u00a0\u00a0$content\u00a0=\u00a0explode(\u00a0&#8216;\u00a0&#8216;,\u00a0get_the_content(),\u00a0$limit\u00a0);<\/li>\n<li><\/li>\n<li>\u00a0\u00a0if\u00a0(\u00a0count(\u00a0$content\u00a0)\u00a0&gt;=\u00a0$limit\u00a0)\u00a0{<\/li>\n<li>\u00a0\u00a0\u00a0\u00a0array_pop(\u00a0$content\u00a0);<\/li>\n<li>\u00a0\u00a0\u00a0\u00a0$content\u00a0=\u00a0implode(&#8221;\u00a0&#8220;,$content).&#8217;&#8230;&#8217;;<\/li>\n<li>\u00a0\u00a0}\u00a0else\u00a0{<\/li>\n<li>\u00a0\u00a0\u00a0\u00a0$content\u00a0=\u00a0implode(&#8221;\u00a0&#8220;,$content);<\/li>\n<li>\u00a0\u00a0}<\/li>\n<li><\/li>\n<li>\u00a0\u00a0$content\u00a0=\u00a0preg_replace(&#8216;\/[.+]\/&#8217;,&#8221;,\u00a0$content);<\/li>\n<li>\u00a0\u00a0$content\u00a0=\u00a0apply_filters(&#8216;the_content&#8217;,\u00a0$content);<\/li>\n<li><\/li>\n<li>\u00a0\u00a0return\u00a0$content;<\/li>\n<li>}<\/li>\n<li>?&gt;<\/li>\n<\/ol>\n<div><\/div>\n<div>You don&#8217;t need to understand every function used inside the function to get the result we want. The point is to &#8220;get&#8221; the idea. Now, to use the function, we simply need to do the following:<\/div>\n<div><\/div>\n<div>&lt;?php\u00a0echo\u00a0jim_content(55);\u00a0\/\/\u00a0display\u00a0page\u00a0content\u00a0limited\u00a0at\u00a055\u00a0chars\u00a0?&gt;<\/div>\n<div><\/div>\n<h4>Installing the plugin<\/h4>\n<p>To install the plugin, we simply upload our file to \/wp-content\/plugins. Then we need to activate it.<\/p>\n<p>The thing is, nothing will happen! That only happens when we manually add the function to our template, as described above.<\/p>\n<p>That&#8217;s the basic idea behind creating a WordPress plugin. You can find more information on everything we&#8217;ve covered in the\u00a0<a href=\"http:\/\/codex.wordpress.org\/Main_Page\" target=\"_blank\" rel=\"external noopener noreferrer\">WordPress documentation\u00a0<\/a>, which today lives mainly in the WordPress Developer Resources at developer.wordpress.org. More specialised tutorials on building more complex plugins will follow. At <a href=\"https:\/\/web-mate.gr\/en\/increase-eshop-sales\/\">WebMate<\/a> we specialise in building plugins for WordPress websites!<\/p>\n<p>Full code:<\/p>\n<p>&lt;?php<br \/>\n\/*<br \/>\nPlugin Name: demo<br \/>\nPlugin URI: http:\/\/www.web-mate.gr<br \/>\nDescription: This is just a simple plugin to update post excerpts.<br \/>\nAuthor: vlagas<br \/>\nVersion: 2.0<br \/>\nAuthor URI: http:\/\/www.web-mate.gr<br \/>\n*\/<\/p>\n<p>function jim_content( $limit ) {<br \/>\n$content = explode( &#8216; &#8216;, get_the_content(), $limit );<\/p>\n<p>if ( count( $content ) &gt;= $limit ) {<br \/>\narray_pop( $content );<br \/>\n$content = implode(&#8221; &#8220;,$content).&#8217;&#8230;&#8217;;<br \/>\n} else {<br \/>\n$content = implode(&#8221; &#8220;,$content);<br \/>\n}<\/p>\n<p>$content = preg_replace(&#8216;\/[.+]\/&#8217;,&#8221;, $content);<br \/>\n$content = apply_filters(&#8216;the_content&#8217;, $content);<\/p>\n<p>return $content;<br \/>\n}<\/p>\n<p>?&gt;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>No one can argue that WordPress hasn&#8217;t changed the world of CMS platforms on the internet: it is currently the most widely used CMS, and the fact that it is open source strengthens its position even further for years to come! Let&#8217;s not forget another point either: WordPress started out as a blogging platform and [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":9317,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","rank_math_title":"How to Build a WordPress Plugin: Beginner Guide | WebMate","rank_math_description":"A beginner guide to building a simple WordPress plugin: folder structure, plugin header, filters, actions and installation. Need a custom plugin? Ask us.","rank_math_focus_keyword":"wordpress plugin"},"categories":[248,239],"tags":[],"class_list":["post-15355","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-website-programming","category-wordpress-en"],"_links":{"self":[{"href":"https:\/\/web-mate.gr\/en\/wp-json\/wp\/v2\/posts\/15355","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/web-mate.gr\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/web-mate.gr\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/web-mate.gr\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/web-mate.gr\/en\/wp-json\/wp\/v2\/comments?post=15355"}],"version-history":[{"count":1,"href":"https:\/\/web-mate.gr\/en\/wp-json\/wp\/v2\/posts\/15355\/revisions"}],"predecessor-version":[{"id":15490,"href":"https:\/\/web-mate.gr\/en\/wp-json\/wp\/v2\/posts\/15355\/revisions\/15490"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/web-mate.gr\/en\/wp-json\/wp\/v2\/media\/9317"}],"wp:attachment":[{"href":"https:\/\/web-mate.gr\/en\/wp-json\/wp\/v2\/media?parent=15355"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/web-mate.gr\/en\/wp-json\/wp\/v2\/categories?post=15355"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/web-mate.gr\/en\/wp-json\/wp\/v2\/tags?post=15355"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}