<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ross Morsali</title>
    <description>The latest articles on DEV Community by Ross Morsali (@rmorse).</description>
    <link>https://dev.to/rmorse</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F625008%2F34bb2f2d-f225-4ae7-8b56-c330ff0aaf77.jpg</url>
      <title>DEV Community: Ross Morsali</title>
      <link>https://dev.to/rmorse</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rmorse"/>
    <language>en</language>
    <item>
      <title>Using PHP namespaces in WordPress plugins + creating an autoloader</title>
      <dc:creator>Ross Morsali</dc:creator>
      <pubDate>Thu, 19 Aug 2021 10:28:44 +0000</pubDate>
      <link>https://dev.to/rmorse/using-php-namespaces-in-wordpress-plugins-creating-an-autoloader-1kl4</link>
      <guid>https://dev.to/rmorse/using-php-namespaces-in-wordpress-plugins-creating-an-autoloader-1kl4</guid>
      <description>&lt;p&gt;I've been working on upgrading one of my WordPress plugins - Search &amp;amp; Filter for some time now, quite the overhaul you might say... &lt;/p&gt;

&lt;p&gt;When planning this update there were a bunch of things &lt;em&gt;I knew&lt;/em&gt; I needed to implement. I won't bore you with all the details, but two tasks I wanted to tick off were:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use PHP namespaces&lt;/li&gt;
&lt;li&gt;Setup an autoloader&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  PHP namespaces
&lt;/h2&gt;

&lt;p&gt;The plugin is getting quite big, and having everything as a class with a unique name was getting a bit messy.&lt;/p&gt;

&lt;p&gt;PHP namespaces solve this issue perfectly as you can scope your classes and then you only need to worry about the uniqueness of your top-level namespace (uniqueness is important in WP plugins in order to avoid conflicts with other plugins).&lt;/p&gt;

&lt;p&gt;This also lends itself very nicely to consistent project structure, because you will likely nest your files in directories matching your namespaces - everything becomes more predictable and uniform.&lt;/p&gt;

&lt;h2&gt;
  
  
  PHP autoloader
&lt;/h2&gt;

&lt;p&gt;When PHP applications grow in size, rather than having to &lt;code&gt;require&lt;/code&gt; every other &lt;code&gt;.php&lt;/code&gt; file in a long list (or by some other method) it's good practice to automatically load them.&lt;/p&gt;

&lt;p&gt;As long as your application has a predictable structure (namespace and class names), you don't need to specify which files to load because we can predict where the relevant file is for a particular class (more on that later).&lt;/p&gt;

&lt;p&gt;What's also great about autoloaders is they only load files at the last minute - when a class is used - giving your application a lighter memory footprint.&lt;/p&gt;

&lt;p&gt;These two concepts absolutely go hand in hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  WordPress enters chat...
&lt;/h2&gt;

&lt;p&gt;Ok, so we know from the above that if our plugin is going to grow that we're going to want to use both namespaces and an autoloader.&lt;/p&gt;

&lt;p&gt;And if we're good developers, we also want to follow the &lt;a href="https://developer.wordpress.org/coding-standards/wordpress-coding-standards/php/"&gt;WordPress coding standards&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Coding standards are a good thing and often in the life of a developer, we'll find conflicting scenarios where we might want to use one set of standards or the other. &lt;/p&gt;

&lt;p&gt;&lt;del&gt;The problem here is, while &lt;a href="https://developer.wordpress.org/coding-standards/wordpress-coding-standards/php/"&gt;WordPress coding standards&lt;/a&gt; cover a lot they don't mention anything about namespaces.&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2023 Correction:&lt;/strong&gt; Looks like &lt;a href="https://developer.wordpress.org/coding-standards/wordpress-coding-standards/php/#declare-statements-namespace-and-import-statements"&gt;a section on namespaces&lt;/a&gt; has now been created and that they follow the same convention described in this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  WordPress PHP Coding Standards
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://developer.wordpress.org/coding-standards/wordpress-coding-standards/php/#naming-conventions"&gt;naming conventions&lt;/a&gt;, it's stated that class names should be cased like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;My_Class
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that they should have a corresponding filename something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class-my-class.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The class name is lowercased, underscores are hyphenated and the filename is prepended with &lt;code&gt;class-&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;So far so good.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Plugin Development Best Practises
&lt;/h3&gt;

&lt;p&gt;There is a &lt;a href="https://developer.wordpress.org/plugins/plugin-basics/best-practices/"&gt;section in the best practises&lt;/a&gt; which is hugely important:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prefix everything!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When a site can have hundreds of plugins, the only way our code won't be messed with is if we prefix everything (including class names).  &lt;/p&gt;

&lt;p&gt;You might want to go with a simple abbreviation prefix, eg, if your plugin was called &lt;code&gt;Speed Up&lt;/code&gt;, you could use &lt;code&gt;SU_My_Class&lt;/code&gt; but in my opinion (and in the examples) the full name is better, so in theory, the ideal class name would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Speed_Up_My_Class
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;It's already getting cumbersome, but it is necessary.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This would ideally be in a file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class-speed-up-my-class.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Switching to namespaces
&lt;/h2&gt;

&lt;p&gt;When structuring a plugin like this it is common to find yourself with tons of files starting with &lt;code&gt;class-speed-up-... .php&lt;/code&gt; - to me it's not particularly elegant, but it's necessary because it accurately represents the class name, which has been prefixed too &lt;code&gt;Speed_Up_...&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If we switch to namespaces we can alleviate some of this pain and repetition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Speed_Up&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;My_Class&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The great thing here is, now &lt;code&gt;My_Class&lt;/code&gt; lives inside the &lt;code&gt;Speed_Up&lt;/code&gt; namespace, we don't need to worry about prefixing it with &lt;code&gt;Speed_Up&lt;/code&gt; again.  By using a namespace, we've kind of prefixed everything inside of it automatically and it won't conflict with other plugins.&lt;/p&gt;

&lt;p&gt;This is how we would use the class now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$my_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Speed_Up\My_Class&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So I think there is not much complexity in this process - just start using them and drop the plugin prefix from all your class names (and filenames) - to be honest I think it's keeping in line with the spirit of &lt;strong&gt;prefix everything&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2023 Update:&lt;/strong&gt; WordPress coding standards now recommends this as &lt;a href="https://developer.wordpress.org/coding-standards/wordpress-coding-standards/php/#declare-statements-namespace-and-import-statements"&gt;the way to use namespaces&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A quick note about namespaces&lt;/strong&gt; - they support nesting!  So you can keep adding names spaces and sub-levels to improve your code organisation - eg:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Speed_Up\Frontend\Scripts\Register
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting up the autoloader
&lt;/h2&gt;

&lt;p&gt;Now we've got the namespace out of the way let's head back to the autoloader.&lt;/p&gt;

&lt;p&gt;There are a few ways to setup autoloaders (each with its own unique benefits) &lt;em&gt;which I'm not going to get into right now&lt;/em&gt; - I'm going to go for the easiest and most straightforward method while also keeping things in the spirit of the WordPress coding standards.&lt;/p&gt;

&lt;p&gt;Setting one up requires using &lt;a href="https://www.php.net/manual/en/language.oop5.autoload.php"&gt;built-in PHP features&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;To implement this in a plugin would require adding some code at the top of your plugins main &lt;code&gt;php&lt;/code&gt; file - if we're sticking with the name &lt;code&gt;speed-up&lt;/code&gt; then it would be located:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wp-content/plugins/speed-up/speed-up.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;We could also create a new file &lt;code&gt;autoload.php&lt;/code&gt; in the root directory to store our autoloader - which is something you'll probably see quite often when reading up on the subject. *&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we add the first example from the PHP docs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nb"&gt;spl_autoload_register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$class_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;include&lt;/span&gt; &lt;span class="nv"&gt;$class_name&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we'll be all set to go! Well, kind of.&lt;/p&gt;

&lt;p&gt;What this code does is register a callback to be used, to specify which filename/path we should look in order to find a class.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Roughly how it works:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When a class is first used, eg: &lt;code&gt;$my_class = new My_Class()&lt;/code&gt; and it is not yet loaded, the function we passed to &lt;code&gt;spl_autoload_register&lt;/code&gt; will be run to try to resolve the filename for the class.  &lt;/p&gt;

&lt;p&gt;It is passed in the &lt;code&gt;$class_name&lt;/code&gt;, and then you can see the file is loaded via &lt;code&gt;include&lt;/code&gt;. In the example above, based on the class name the file&lt;/p&gt;

&lt;p&gt;&lt;code&gt;My_Class.php&lt;/code&gt; would attempt to be loaded.&lt;/p&gt;

&lt;p&gt;Also, something worth observing, when a class is used in a namespace, the full namespace + class name is passed through &lt;code&gt;$class_name&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing an autoloader for a WordPress plugin
&lt;/h3&gt;

&lt;p&gt;So let's apply the coding standards to the autoloader and calculate the correct file path based on namespace and class name.&lt;/p&gt;

&lt;p&gt;What we want to achieve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Class filenames must be prefixed with &lt;code&gt;class-&lt;/code&gt;...&lt;/li&gt;
&lt;li&gt;Class filenames should be lowercase&lt;/li&gt;
&lt;li&gt;Underscores should be replaced with dashes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And we're going to convert namespaces. Classes belonging to a namespace should live in a folder (namespace name) that follows the conversion process of a class. So we need to add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Namespace names will be converted to lowercase&lt;/li&gt;
&lt;li&gt;Namespace names will have underscores replaced with dashes&lt;/li&gt;
&lt;li&gt;Namespaces will be folders so convert &lt;code&gt;\&lt;/code&gt; to a directory path&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition - because the root plugin folder "is the plugin" and already has a directory name relevant to the plugin name, eg - &lt;code&gt;speed-up&lt;/code&gt; we shouldn't create another folder called &lt;code&gt;speed-up&lt;/code&gt; just to match our &lt;code&gt;Speed_Up&lt;/code&gt; plugin namespace, it's unnecessarily repetitive and we'll actually remove that, and instead, we'll create a folder called &lt;code&gt;includes&lt;/code&gt; for our classes instead.&lt;/p&gt;

&lt;p&gt;So our plugin structure would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;speed-up // top-level plugin folder
-- speed-up.php // main plugin file
-- readme.txt // required with every plugin
-- includes // this folder is where we store all our classes
---- database // folder for the sub namespace Database
------ class-connect.php // class Connect
       class-worker.php // class Worker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The class &lt;code&gt;Worker&lt;/code&gt; in &lt;code&gt;includes\database\class-worker.php&lt;/code&gt; above would be accessed like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Speed_Up\Database\Worker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For me, this is the perfect balance of adding namespaces to WordPress plugins while keeping in the spirit of the coding standards.&lt;/p&gt;

&lt;h3&gt;
  
  
  The code
&lt;/h3&gt;

&lt;p&gt;To parse the name space and class names, and follow those above conversion rules (class name -&amp;gt; path + filename) would result in some PHP code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Define the main autoloader&lt;/span&gt;
&lt;span class="nb"&gt;spl_autoload_register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'speed_up_autoloader'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;speed_up_autoloader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$class_name&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// These should be changed for your particular plugin requirements&lt;/span&gt;
    &lt;span class="nv"&gt;$parent_namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Speed_Up'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$classes_subfolder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'includes'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nb"&gt;strpos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$class_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$parent_namespace&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$classes_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;realpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nf"&gt;plugin_dir_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;__FILE__&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="no"&gt;DIRECTORY_SEPARATOR&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$classes_subfolder&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="no"&gt;DIRECTORY_SEPARATOR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Project namespace&lt;/span&gt;
        &lt;span class="nv"&gt;$project_namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$parent_namespace&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'\\'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$project_namespace&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Remove top-level namespace (that is the current dir)&lt;/span&gt;
        &lt;span class="nv"&gt;$class_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$class_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$length&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// Swap underscores for dashes and lowercase&lt;/span&gt;
        &lt;span class="nv"&gt;$class_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str_replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;strtolower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$class_file&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Prepend `class-` to the filename (last class part)&lt;/span&gt;
        &lt;span class="nv"&gt;$class_parts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;explode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'\\'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$class_file&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$last_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$class_parts&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$class_parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$last_index&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'class-'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$class_parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$last_index&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="c1"&gt;// Join everything back together and add the file extension&lt;/span&gt;
        &lt;span class="nv"&gt;$class_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;implode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="no"&gt;DIRECTORY_SEPARATOR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$class_parts&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$classes_dir&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$class_file&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;is_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$location&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;require_once&lt;/span&gt; &lt;span class="nv"&gt;$location&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've also setup a tiny demo plugin using the above for you to play with over on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/rmorse/speed-up"&gt;Github Repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Are you doing it a different way? No technique is perfect and there is always room for improvement - let me know your thoughts!&lt;/p&gt;

&lt;p&gt;If you want to read more articles like this you can &lt;a href="https://twitter.com/rmors_"&gt;follow me on Twitter&lt;/a&gt; to keep up to date.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>php</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to create a (multiple) block plugin for WordPress</title>
      <dc:creator>Ross Morsali</dc:creator>
      <pubDate>Sun, 08 Aug 2021 09:56:44 +0000</pubDate>
      <link>https://dev.to/rmorse/how-to-create-a-multiple-block-plugin-for-wordpress-mpm</link>
      <guid>https://dev.to/rmorse/how-to-create-a-multiple-block-plugin-for-wordpress-mpm</guid>
      <description>&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@elodieoudot?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Elodie Oudot&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/lego-blocks?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Want the files?&lt;/strong&gt;&lt;br&gt;
If you're impatient like me, you can go straight for &lt;a href="https://github.com/rmorse/multiple-blocks-plugin" rel="noopener noreferrer"&gt;the code on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a single block plugin
&lt;/h2&gt;

&lt;p&gt;There's already a great package out there for creating a single block plugin, so we're going to use that as the foundation for creating our multiple block plugin.&lt;/p&gt;

&lt;p&gt;Since the release of the &lt;a href="https://developer.wordpress.org/block-editor/reference-guides/packages/packages-create-block/" rel="noopener noreferrer"&gt;@wordpress/create-block&lt;/a&gt; package, creating a block plugin with an an awesome development setup (scaffolding) has gotten a lot easier - it takes a lot of the hard work out of setting up webpack, a transpiler, scss + a whole lot more - &lt;em&gt;although I'm sure some of you would still rather roll your own&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If you want to get going quickly I recommend getting familiar - and this post assumes you &lt;strong&gt;already know how to use &lt;code&gt;@wordpress/create-block&lt;/code&gt;&lt;/strong&gt;, but we'll still go through the steps from the beginning.&lt;/p&gt;

&lt;p&gt;Anyway, I saw a question recently (I think on Twitter) - something like, "How can I create multiple blocks with this tool"?&lt;/p&gt;

&lt;p&gt;So I've been digging into this and that's what I aim to share in this post.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up &lt;code&gt;@wordpress/create-block&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;I'll try to be brief on this, but you can follow the link above for a more in depth setup guide.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Lets start by creating a new plugin using &lt;code&gt;@wordpress/create-block&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;In a local development environment, locate your &lt;code&gt;/wp-content/plugins/&lt;/code&gt; directory and open a terminal from there, then enter:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npx @wordpress/create-block multiple-blocks-plugin


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;It can take some time to setup, grab a drink...&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This creates the main plugin directory with the name &lt;code&gt;multiple-blocks-plugin&lt;/code&gt; and the default project structure.  Enter this directory and start the dev script:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

cd multiple-blocks-plugin
npm run start


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now the plugin is ready to use and it can be enabled via the plugins page in your WordPress dashboard.&lt;/p&gt;

&lt;p&gt;Once enabled, verify that setup has gone well by adding the block via the post editor - it will be called &lt;strong&gt;Multiple Blocks Plugin&lt;/strong&gt;:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41tcahli846qqbyph1i4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41tcahli846qqbyph1i4.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Existing structure
&lt;/h2&gt;

&lt;p&gt;Assuming the above went well, we can now take a look at the project structure, and visualise how this needs to be re-arranged in order to support multiple blocks.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I won't be explaining all the files / folders, just the relevant ones.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;multiple-blocks-plugin.php&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This is the main plugin file, and it's incredibly simple - it calls &lt;code&gt;register_block_type()&lt;/code&gt; with the current directory as an argument, which then tries to locate a &lt;code&gt;block.json&lt;/code&gt; file (and registers it).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;block.json&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This is the main configuration file for your block, &lt;a href="https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/" rel="noopener noreferrer"&gt;where you define basic settings&lt;/a&gt; - it also includes references to the other files that are used with your block (the editor script, editor style and shared style).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;src&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;src&lt;/code&gt; directory is where you'll be doing most of the work on your block. This is the place you'll usually add your block editor functionality as well as your styles.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;build&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;We're using a modern development stack - which means we can write ESNext and JSX code in our project, but before it can be used on all browsers it must be converted (transpiled). This process is handled automatically and the result is placed in this directory.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;package.json&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Amongst other things, this file contains the &lt;code&gt;npm run start&lt;/code&gt; script used to build your block, we'll be updating this and adding scripts for each block you want to create.&lt;/p&gt;

&lt;h2&gt;
  
  
  Convert into a multiple blocks plugin
&lt;/h2&gt;

&lt;p&gt;So now let's begin the process of transforming the existing structure, into a structure that supports multiple blocks.&lt;/p&gt;

&lt;p&gt;The main thing to note here is, &lt;code&gt;block.json&lt;/code&gt;, &lt;code&gt;src&lt;/code&gt;, and &lt;code&gt;build&lt;/code&gt; all belong to the "block", whereas all the other files in the project are related to the plugin / development setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  0. Create a directory to house all blocks
&lt;/h3&gt;

&lt;p&gt;Let's name this something imaginative, like... &lt;code&gt;blocks&lt;/code&gt;:&lt;br&gt;
&lt;code&gt;multiple-blocks-plugin/blocks/&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The next steps can be repeated for every new block you want to create.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  1. Create a directory for the block
&lt;/h3&gt;

&lt;p&gt;In this case we'll use &lt;strong&gt;buy-button&lt;/strong&gt;:&lt;br&gt;
&lt;code&gt;multiple-blocks-plugin/blocks/buy-button/&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Identify &amp;amp; copy the block related files
&lt;/h3&gt;

&lt;p&gt;We can move (if it's the first time doing this, otherwise copy) &lt;code&gt;block.json&lt;/code&gt;, &lt;code&gt;src&lt;/code&gt; and &lt;code&gt;build&lt;/code&gt; in to the new block directory.&lt;/p&gt;

&lt;p&gt;Your directory structure should look something like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffykpqxkh7bdo21zmrrxb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffykpqxkh7bdo21zmrrxb.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Rename block settings in block.json
&lt;/h3&gt;

&lt;p&gt;This step is important, we need to update the block name and title to something unique. These are the two properties to change:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"multiple-blocks-plugin/buy-button"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Buy Button"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Take a note of the new &lt;strong&gt;name&lt;/strong&gt; - &lt;code&gt;multiple-blocks-plugin/buy-button&lt;/code&gt; - we'll be needing it in the next step.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Update reference to the new block name
&lt;/h3&gt;

&lt;p&gt;In your blocks &lt;code&gt;src&lt;/code&gt; directory, edit &lt;code&gt;index.js&lt;/code&gt;:&lt;br&gt;
&lt;code&gt;multiple-blocks-plugin/buy-button/src/index.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and modify the line containing &lt;code&gt;registerBlockType()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Lets update the name to use our new name (from the last step):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;registerBlockType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;multiple-blocks-plugin/buy-button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  5. Update CSS classes
&lt;/h3&gt;

&lt;p&gt;There are two SCSS files to locate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;blocks/buy-button/src/style.scss&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;blocks/buy-button/src/editor.scss&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They both contain the class:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;

&lt;span class="nc"&gt;.wp-block-create-block-multiple-blocks-plugin&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;However the class name is based on our block name and &lt;strong&gt;should be changed to&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;

&lt;span class="nc"&gt;.wp-block-multiple-blocks-plugin-buy-button&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  6. Update &lt;code&gt;multiple-blocks-plugin.php&lt;/code&gt; to reference the new location
&lt;/h3&gt;

&lt;p&gt;Here we simply want to change the directory used in &lt;code&gt;register_block_type&lt;/code&gt; (if it's the first time doing this) or add an additional &lt;code&gt;register_block_type&lt;/code&gt; to reference our new block directory.&lt;/p&gt;

&lt;p&gt;We can update the main function like this:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;create_block_multiple_blocks_plugin_block_init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;register_block_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nf"&gt;plugin_dir_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;__FILE__&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'blocks/buy-button/'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Additional blocks would be registered here&lt;/span&gt;
    &lt;span class="c1"&gt;// register_block_type( plugin_dir_path( __FILE__ ) . 'blocks/another-block/' );&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  7. Create scripts for your new block in &lt;code&gt;package.json&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;When we use &lt;code&gt;npm run start&lt;/code&gt; we're running a script defined in &lt;code&gt;package.json&lt;/code&gt;, using some default settings.  &lt;/p&gt;

&lt;p&gt;Because we moved our block files, we'll need to create scripts to build them in their new locations.  In the &lt;code&gt;scripts&lt;/code&gt; section of &lt;code&gt;package.json&lt;/code&gt; you'll need to add:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"start:buy-button"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wp-scripts start blocks/buy-button/src/index.js --output-path=blocks/buy-button/build/"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"build:buy-button"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wp-scripts build blocks/buy-button/src/index.js --output-path=blocks/buy-button/build/"&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Notice that we specified an input path pointing to the &lt;code&gt;src&lt;/code&gt; directory of our block, and output path pointing the &lt;code&gt;build&lt;/code&gt; directory of our block, and that we updated the scripts by adding our block name &lt;code&gt;:buy-button&lt;/code&gt; to the script name.&lt;/p&gt;

&lt;p&gt;With the above addition, this is the new way to start your dev build (from the command line):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npm run start:buy-button


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You'll need to use that instead of just &lt;code&gt;npm run start&lt;/code&gt; for running in development mode and for production you can use:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npm run build:buy-button


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And that's it, you're good to go - what you do with these blocks is up to you!&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;So the first run through, we essentially moved the default generated block files, into a sub-directory and re-wired the project to use the new name + location. &lt;/p&gt;

&lt;p&gt;For each new block you want to create, the process will be similar, just follow &lt;strong&gt;steps 1 - 7&lt;/strong&gt;. All you need to do is copy the default block files over (from an existing project, or grab a fresh copy from &lt;code&gt;@wordpress/create-block&lt;/code&gt;) - &lt;/p&gt;

&lt;p&gt;Note: the &lt;code&gt;build&lt;/code&gt; folder is in fact not necessary (although we moved it earlier) - it is automatically generated when you run the command line scripts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Repo + files
&lt;/h3&gt;

&lt;p&gt;The project is ready to be used and comes with 2 blocks - &lt;strong&gt;Buy Button&lt;/strong&gt; and &lt;strong&gt;Hero Block&lt;/strong&gt; (they don't do anything though) - but I do recommend learning the above process and creating additional blocks yourself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/rmorse/multiple-blocks-plugin" rel="noopener noreferrer"&gt;Download from GitHub&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Questions + feedback are most welcome.&lt;/p&gt;

&lt;p&gt;If you liked this post, come and say hi over &lt;a href="https://twitter.com/rmors_" rel="noopener noreferrer"&gt;on Twitter&lt;/a&gt; - my plan is to create more WordPress developer related content in the near future.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>tutorial</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
