2
Plugin Framework

REQUIREMENTS FOR PLUGINS

The WordPress plugin system is flexible and allows for plugins to be either a single file or a folder with many files. In this section, you'll learn the basics of creating a plugin.

Naming Your Plugin

The most important thing when naming your plugin is for it to be something unique. It's also good practice for the name to reflect what the plugin actually does. For example, you wouldn't want to name a forum plugin “Joe's Plugin” because that doesn't tell potential users anything about what your plugin does.

You also need to consider whether your plugin name is too generic. It's possible that the name has already been taken by another plugin developer. You can check existing plugins in the WordPress Plugin Directory (https://wordpress.org/plugins).

Because there are thousands of existing plugins, some developers prefix their plugin name with their business name. For example, if your business name is “Super Duper,” you might name a potential forum plugin “Super Duper Forums.” This allows you to better attach your brand to your plugin and keep the name unique.

Using a Folder

While WordPress does allow plugins to be a single file, it is generally not good practice to use this method. Instead, it is standard practice to use a folder to contain your plugin. The vast majority of plugins will contain multiple files, such as PHP files, CSS and JavaScript assets, and other build files.

When creating a plugin, it should ideally match your plugin name. Plugin folder names should be hyphenated and lowercase. It should not contain spaces, underscores, uppercase letters, or nonalphanumeric characters. The plugin folder name must also match the plugin text domain when preparing your plugin for translations (see Chapter 11, “Internationalization”) if you plan to submit it to the official plugin repository.

Using the previous “Super Duper Forums” plugin as an example, its folder name should be super‐duper‐forums.

BEST PRACTICES

With any code base, developers should follow a common set of best practices. This is no different with WordPress plugins. By strictly following the practices laid out in this section, you'll have a solid foundation for your plugin. You'll also learn how to organize your plugin files and subfolders.

Namespace Everything

If you have a function named get_post(), it will conflict with WordPress’ own get_post() function and result in a fatal error. That's not a good user experience. Writing good code means making sure that your code doesn't conflict with other developers' code. The best way to ensure that is to prefix or namespace all your classes, functions, and anything else within the global namespace.

Throughout most of WordPress’ existence, it has supported versions of PHP versions earlier than 5.3, which is the version of PHP that standardized namespaces. This meant that it was standard practice to use a faux namespace by prefixing classes and functions. Prefixes should be unique to the plugin. The WordPress coding standards recommend naming classes and functions using snake case. Therefore, a function named get_post() would become prefix_get_post(), and a class named Post would become Prefix_Post.

WordPress 5.2 changed its minimum PHP requirements to PHP 5.6. This means that plugin authors who want to support the same PHP versions as WordPress are no longer tied to the old practice of using prefixes. For this reason, it's probably best to look at other standards for naming, such as those outlined in the PHP‐FIG standards (https://www.php-fig.org).

For the purposes of this book, the recommendation for namespacing your code will be to use the built‐in method of namespacing in PHP. Namespaces allow you to group your code under a unique name so that it doesn't conflict with other developers' code. Using the “Super Duper Forums” plugin example, your namespace would be called SuperDuperForums.

Namespaces must be the first code, excluding the opening <?php tag and inline comments, in a PHP file. In the following example, see how a custom class named Setup is handled. Because it is under the SuperDuperForums namespace, there's no need to prefix it.

<?php
namespace SuperDuperForums;
 
class Setup {
      public function boot() {}
}

Class and function names are not the only consideration when namespacing code. There are other times when you'll have things in the global namespace that might conflict with other plugins running in WordPress. Such cases may include storing options in the database (see Chapter 3, “Dashboard and Settings”) or loading a JavaScript file (see Chapter 6, “JavaScript”). In such cases, it's generally best practice to prefix option names with your plugin name, such as super_duper_forums_ option_name, and prefix script handles similarly, such as super‐duper‐forums‐ script‐name.

You may have noticed that the option name used snake case (underscores) and the script handled used kebab case (hyphenated) in the previous example. The difference in practice has arisen over the years and can be confusing to new plugin developers. In general, anything referred to as a handle is in kebab case, and everything else is in snake case. Often such differences are superficial and not overly important. When in doubt, stick with snake case, and you'll be alright.

File Organization

When building your plugin, it's important to think about how your files should be organized. While you can change some things around later, getting started with a solid structure will make it easier to build out the plugin's features in the long run.

The most important and only required file for any plugin to have is its primary PHP file. This file can be named anything and must sit in the root of your plugin folder. If your primary file is named plugin.php, it will be located at /super‐duper‐forums/plugin.php.

There are two common practices for naming the primary plugin file. Many plugin authors name this file the same as the folder, such as super‐duper‐forums.php. The less‐common practice is to simply name this plugin.php. You may decide to choose something else entirely. Over time as you develop plugins, you'll likely want to have a standard naming scheme that best suits you or your team.

In modern plugin development, you'll most likely have JavaScript build tools, config files, and all sorts of other files that take up space in the root of your plugin folder. Putting all your plugin files in the root will likely clutter things and make it hard to find things. It's best to only keep your primary plugin file in the root and all other plugin code within subfolders. The exception to this rule would be the uninstall.php file (see the “Uninstall.php” section later in this chapter).

Folder Structure

In professional development, it's important to create a folder structure that is understandable at a glance and easy to maintain. Most plugin developers will create separate folders to house their PHP code apart from resources, assets, or other front‐end code in a folder with a name such as /src, /inc, /includes, or /app. Within the larger PHP development community, it is standard practice to name this folder /src because this is the folder where your “source” code lives.

The naming of the assets or resources folder is also varied with plugins. Often this folder is named /assets, /dist, or /public. Most likely, you'll want to have separate development and production folders if you use a build system such as webpack to bundle your final asset files.

The following is an example of how a plugin folder structure may be organized. Some of the files in this list are covered later in this chapter.

  • plugin.php: Primary plugin file
  • uninstall.php: Uninstall file
  • /src: PHP source code
    • Activator.php: Activation class
    • Deactivator.php: Deactivation class
    • Plugin.php: Primary plugin class
  • /resources: Development asset files
  • /css: Development CSS
    • /js: Development JavaScript
  • /public: Production asset files
    • /css: Production CSS
    • /js: Production JavaScript

This is a clean structure that will help you maintain your plugin code over time. You may choose a different structure for your own projects.

When using namespaces as described in the “Namespace Everything” section of this chapter, it is standard practice to have a folder structure that matches how your namespaces and subnamespaces are set up so that it is easy to autoload the files using a system that follows the PHP‐FIG autoloading standard (https://www.php-fig.org/psr/psr-4).

With a fully qualified class name of PDEVPostEdit, you'd have the following structure within your /src folder:

  • /Post: Subnamespace
    • Edit.php: Class file

Following this structure will tie your code and namespace structure directly to your folder structure. It makes it simple for you and other developers to navigate your project's files and folders by just looking at the namespace and class name.

This is the standard used by the larger PHP community and has been for many years. Much of the WordPress community is still light‐years behind in following this standard, but it is beginning to catch on with more and more plugin developers.

PLUGIN HEADER

For WordPress to recognize a plugin, the plugin's primary PHP file must have what's called a plugin header at the top of the file. This tells WordPress that this particular file is the file that it must load to your plugin. WordPress plugins can be and do anything, but this is the only hard requirement for a plugin to function.

Creating the Header

The plugin header is nothing more than a normal PHP inline code comment with some special formatting that WordPress can recognize. The following is an example of a plugin header:

<?php
/**
 * Plugin Name:       My Plugin
 * Plugin URI:        https://example.com/plugins/pdev
 * Description:       A short description of the plugin.
 * Version:           1.0.0
 * Requires at least: 5.3
 * Requires PHP:      5.6
 * Author:            John Doe
 * Author URI:        https://example.com
 * License:           GPL v2 or later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       pdev
 * Domain Path:       /public/lang
 */

Each line is called a header file and provides some info to WordPress about your plugin. The only required field for the plugin to work is the Plugin Name field. Each field should be straightforward to understand. The following is a brief description of what each field sets:

  • Plugin Name: The name for your plugin
  • Plugin URI: A URI with more information about your plugin
  • Description: A brief summary that describes what your plugin does
  • Version: The current version of your plugin, which should be incremented with each update
  • Requires at least: The minimum version of WordPress required for your plugin to work
  • Requires PHP: The minimum version of PHP required for your plugin to work
  • Author: Your or your team/business name
  • Author URI: The link to your website
  • License: The license that the plugin is distributed under
  • License URI: A link to the full text of the license
  • Text Domain: The text domain used for internationalizing your plugin (see Chapter 11 for more information)
  • Domain Path: The relative path to where translation files are located in your plugin
  • Network: An optional field that can be set to true for plugins that can only be activated across the entire network on a multisite installation

Plugin License

When distributing your plugin to others, it's important to have a clear license so that you both protect your own copyright and make sure anyone who receives your plugin has a clear understanding of what their rights are. WordPress is licensed under the GNU General Public License (GPL), version 2 or later. Any plugins distributed should use a license that is compatible with the GPL.

The GPL recommends placing the following copyright notice in every source file for your plugin. However, most plugins only place this after the plugin header in the primary plugin file.

<?php
/*
Copyright (C) <year> <name of author>
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

You need to replace the <year> and <name of author> snippets in that notice with the year the code was created and your name. Once you add the notification to your plugin file(s), it will then be licensed under the GPL.

If working with a client or employer and not distributing the plugin to the public in any way, your plugin may not need a license. Copyright and/or license should be determined by your contract and what you and your client/employer agree to.

DETERMINING PATHS

Perhaps one of the toughest hurdles to jump when building WordPress plugins is simply figuring out the appropriate path when loading or referencing a file. Because you as a plugin developer do not control how the user chooses to set up their WordPress installation, you cannot rely on a specific pattern.

Plugin Paths

There are two types of paths that you might be concerned with when building WordPress plugins. The first is the local path to files on the server. The second is URL paths, which may be necessary for loading JavaScript files, CSS stylesheets, or other assets. You may also need to link to a specific URL within the WordPress installation itself.

Because WordPress provides the ability for users to move their wp‐content folder (where plugins are located) to any location on the server, it's important to use the standard WordPress functions for determining the correct path.

Local Paths

Local paths reference locations on the server. PHP provides easy methods for determining paths for almost every case needed. However, to be on the safe side, it's best to use WordPress functions where possible. The plugin_dir_path() function provides an easy way to get the filesystem directory path to your plugin.

<?php $path = plugin_dir_path( $file ); ?>

Parameters:

  • $file (string, required): The filename in the current directory path

The following example will print the path of the current directory of the file passed in with a trailing slash using PHP's __FILE__ constant:

<?php echo plugin_dir_path( __FILE__ ); ?>

That code should output a path similar to the following:

/public_html/wp-content/plugins/pdev/

Any file can be passed into the function. The resulting path will point to wherever the file lives in your plugin. If passing in __FILE__ from the primary plugin file, it'll be the path to the root of your plugin. If passing it in from a subfolder in your plugin, it will return the path to the subfolder in your plugin.

Assuming you needed to load a file named /src/functions.php from your plugin that houses some custom functions, use the following code:

<?php include plugin_dir_path( __FILE__ ) . '/src/functions.php'; ?>

It is common practice for plugin authors to store this path as a variable or constant in the plugin's primary file for quick access to the plugin's root folder path, as shown in the following example code:

<?php define( 'PDEV_DIR', plugin_dir_path( __FILE__ ) ); ?>

This allows you to reference PDEV_DIR any time you need it from anywhere in the plugin without having to think about file paths.

URL Paths

Referencing URL paths can be tougher than local paths because there's usually no good way to determine this via standard PHP functions or constants alone. You'll need to rely on WordPress to get the correct path.

The primary use case for getting a URL path will be determining the path to an asset (e.g., JavaScript, CSS, or image files) within your plugin. WordPress provides the plugin_dir_url() function to handle this use case.

<?php $url = plugin_dir_url( $file ); ?>

Parameters:

  • $file (string, required): The filename in the current directory path

WordPress will automatically convert any filename passed in to an appropriate URL equivalent. See the following example of passing in the filename from within the primary plugin file:

<?php echo plugin_dir_url( __FILE__ ); ?>

That code will output something like the following URL with a trailing slash:

https://example.com/wp-content/plugins/pdev/

If you wanted to determine the path of a JavaScript file located at /public/js/example.js in your plugin, you'd use the following code:

<?php $url = plugin_dir_url( __FILE__ ) . 'public/js/example.js'; ?>

You can use this to correctly get the URL path to any location in your plugin. Like its plugin_dir_path() counterpart, you can pass in any filename in your plugin to determine the appropriate URL for any location.

WordPress also provides a plugins_url() function. plugin_dir_url() is a wrapper for this function. For most purposes, these two functions can almost be used interchangeably, but there are some important differences.

<?php $url = plugins_url( $path = '', $plugin = '' ); ?>

Parameters:

  • $path (string, optional): A path to append to the end of the URL
  • $plugin (string, optional): The full path to a file within the plugin

If no parameters are provided, the function will return the URL to the plugin's directory for the WordPress installation. It also does not add a trailing slash to the end of the URL. For most cases, it's usually best to stick with plugin_dir_url(). However, this function is available if needed.

Other than determining the URL path to files within your plugin, you may need to determine the URL for a particular page or directory within the WordPress installation. WordPress has a number of useful functions that return the necessary information.

  • site_url(): URL path to where WordPress is installed
  • home_url(): URL path to the site's homepage
  • admin_url(): URL path to the WordPress admin
  • rest_url(): URL path the REST API endpoint
  • includes_url(): URL path to the WordPress includes directory
  • content_url(): URL path to the WordPress content directory

All of these URL functions accept an optional first parameter of $path, which is appended to the end of the URL if provided. The following example shows how to retrieve the URL path to the General Settings page in the admin:

<?php $url = admin_url( 'options-general.php' ); ?>

With the exception of the content_url() function, each of these functions also accepts an optional second parameter of $scheme, which allows you to manually set the protocol, such as 'http' or 'https'. In almost all cases, you should not set this parameter and should instead allow WordPress to automatically determine the appropriate URL scheme.

First‐time WordPress developers will also sometimes confuse site_url() and home_url(). WordPress can be installed in a subdirectory on the server while allowing the actual site to be located elsewhere. Unfortunately, the function names are part of a legacy code base and have stuck around. The trick is to remember that the “home” in home_url() refers to the URL of the site, and the “site” in site_url() refers to the URL of the WordPress installation.

If WordPress is installed in a subdirectory, site_url() might point to a URL like https://example.com/wordpress, while home_url() points to https://example.com.

ACTIVATE/DEACTIVATE FUNCTIONS

WordPress provides standard activation and deactivation hooks that allow any plugin to run code when it is activated or deactivated, respectively. This section walks through how to use both.

Plugin Activation Function

When building plugins, you'll often need to execute some code when the user first activates it. One common use case is adding custom capabilities to the administrator role (see Chapter 9, “Users and User Data”) for something like a custom post type (see Chapter 8, “Content”) that your plugin is registering. Or, you may need to set up a particular option for your plugin to perform.

WordPress provides the register_activation_hook() function that allows you to pass in a callback for handling any activation code you need to run.

<?php register_activation_hook( string $file, callable $function ); ?>

Parameters:

  • $file (string, required): Filesystem path to the primary plugin file
  • $function (callable, required): The PHP callable to be executed when the plugin is activated

It's generally best to separate your activation code from the rest of your plugin code simply for organizational purposes. The following example shows how to register an activation hook that points to a class located at src/Activation.php in your plugin and executes its activate() method:

<?php
 
namespace PDEV;
 
register_activation_hook( __FILE__, function() {
       require_once plugin_dir_path( __FILE__ ) . 'src/Activation.php';
       Activation::activate();
} );

With the activation hook callback registered, you need to figure out what things you need to set upon activation. The following example gets the administrator role object and adds a custom capability to it:

<?php
 
namespace PDEV;
 
class Activation {
 
       public static function activate() {
 
             $role = get_role( 'administrator' );
 
             if ( ! empty( $role ) ) {
                  $role->add_cap( 'pdev_manage' );
            }
       }
}

There is no limit to what code you can run upon activation. It's a great time to run anything that needs to be set only once or things that shouldn't be run on every page load. For example, if your plugin needs to create custom database tables, this would be the time to do it.

While it is common practice with some plugin authors, you usually shouldn't set plugin database options at this point. It's almost always better to use sane defaults for any options your plugin has and not clutter the database until the end user has explicitly decided to save on your plugin settings screen (see Chapter 3).

Plugin Deactivation Function

Like the activation function, WordPress also allows you to execute code from a registered deactivation callback via the register_deactivation_hook() function. The following example includes the src/Deactivation.php class and executes its deactivate() method:

<?php
 
namespace PDEV;
 
register_deactivation_hook( __FILE__, function() {
       require_once plugin_dir_path( __FILE__ ) . 'src/Deactivation.php';
       Deactivation::deactivate();
} );

Once you've registered your deactivation callback, you need to run some code on deactivation. The following is an example of how to set up your Deactivation class:

<?php
 
namespace PDEV;
 
class Deactivation {
 
       public static function deactivate() {
              // Run your deactivation code here.
       }
}

Like with the activation hook, you have the freedom to run any code that you need when a user decides to deactivate your plugin.

Deactivate Is Not Uninstall

Setting up a deactivation callback is often unnecessary because most of the things you might think you'd need to unset on deactivation should actually happen when a user uninstalls the plugin. Deactivation is not an appropriate time to delete plugin options, remove database tables, delete user content, or perform any other highly destructive actions.

Users and even WordPress itself may deactivate a plugin for any number of reasons. You don't want your plugin users to lose any important data when deactivating only to reactivate and find their settings or content gone. Use with extreme caution.

UNINSTALL METHODS

Cleaning up anything left behind when a user uninstalls your plugin is an important aspect of developing plugins professionally. Running an uninstall procedure takes little work on your part but makes sure that users can trust that they can use your plugins without those plugins leaving unwanted data behind.

Why Uninstall Is Necessary

If you install an app on your mobile phone and decide at some point that you no longer want to use that app, you'll delete or “uninstall” it. You wouldn't want the app to leave behind all of its settings or any other data that is no longer useful. WordPress plugins are no different. Users should feel confident that their site doesn't have cruft left over from every plugin they've used or even just tested and decide it wasn't for them.

If there's an ultimate “no‐no” in plugin development, it's to not tidy up after yourself. When your plugin is uninstalled, make sure to delete any options or other data that your plugin has added.

However, there are times when you want to ignore this rule. In general, user‐created content, such as that created by custom post types or custom database tables, may need to be retained. In these situations, it's best to provide a setting that a user can opt into that allows you to delete that data on uninstall. The rule of thumb here is to always be respectful of their content. When in doubt, get the user's permission before deleting anything they might want to keep.

WordPress provides two different methods for uninstalling a plugin: the uninstall.php file and the uninstall hook.

Uninstall.php

The first method of uninstalling a plugin is by creating an uninstall.php file in the root of your plugin folder. This is the method that you'll most likely be using and is the recommended route to take.

Using uninstall.php is the preferred method of uninstalling a plugin because it isolates your uninstall code from the rest of your plugin and doesn't allow arbitrary code to run from your other plugin files. Ideally, your plugin should be structured such that arbitrary code is never run. However, uninstall.php protects against this and makes sure only the code contained within the file is executed.

It's also important to check that WP_UNINSTALL_PLUGIN is set before executing your uninstall code. Otherwise, it's possible the file will be inadvertently called and your plugin will delete everything when it shouldn't.

In the following example, you can see that the uninstall procedure checks the constant and removes the pdev_manage capability added in the “Plugin Activation Hook” section earlier in this chapter:

<?php

 
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
       wp_die( sprintf(
            __( '%s should only be called when uninstalling the plugin.', 'pdev' ),
            __FILE__
       ) );
       exit;
}
 
$role = get_role( 'administrator' );
 
if ( ! empty( $role ) ) {
       $role->remove_cap( 'pdev_manage' );
}

Uninstall Hook

WordPress provides an uninstall hook similar to its activation and deactivation hooks outlined earlier in this chapter. If no uninstall.php file exists for the plugin, WordPress will look for a callback registered via the register_uninstall_hook() function.

<?php register_uninstall_hook( $file, $callback ); ?>

Parameters:

  • $file (string, required): The primary plugin file
  • $callback (callable, required): A function to execute during the uninstall process

Now look at the following example of how a plugin uninstall function works:

<?php
 
register_uninstall_hook( __FILE__, 'pdev_uninstall' );
 
function pdev_uninstall() {
       $role = get_role( 'administrator' );
 
       if ( ! empty( $role ) ) {
             $role->remove_cap( 'pdev_manage' );
       }
}

That example performs the same action as the uninstall.php file from the previous section in this chapter. However, you may have noted an important difference. There's no need to check the WP_UNINSTALL_PLUGIN constant because it's not set in the uninstall callback and unnecessary.

It's also important to use $this or an object reference when registering an uninstall hook because this callback reference is stored in the database and is unique to the page load when it is stored.

CODING STANDARDS

Following a set of standards when developing plugins professionally is important because it makes long‐term maintenance of your code easier and also allows other developers to quickly learn from or contribute to your plugin. WordPress maintains a coding standard for the core source code. It is a good starting point when building plugins. You can view the WordPress coding standards at https://make.wordpress.org/core/handbook/best-practices/coding-standards.

WordPress has more than 15 years of legacy code, and sometimes its standards do not align with the standards of the larger PHP community. This can be off‐putting for some PHP developers new to the WordPress community. You may also want to follow PHP Recommended Standards (PSRs) created and maintained by the PHP Framework Interprop Group (PHP‐FIG) for the larger PHP community. You can find these standards at https://www.php-fig.org/psr.

The most important thing is to maintain consistency in your code base, regardless of the coding standards that you follow.

Document Your Code

One of the worst things you can do as a developer is to never document your code. While you should always strive for your code to be self‐documenting by naming things in ways that make sense and limiting functions/classes to a single responsibility, documenting your code is just as important as the code itself.

Imagine writing a large plugin for a client today and not documenting what everything does. That same client calls you up in two years to make some big updates for them. Can you honestly say that you'll completely understand the code that you wrote two years ago? Even if you could, what about another developer? You may think that it's not your problem, but that could earn you a poor reputation in the WordPress developer community. You should be a “good citizen” and help your fellow developers.

Documentation is also important when building plugins for public release. For others to contribute code to your plugin through patches or pull requests, other developers should have enough documentation to understand any decisions that you made with the code.

WordPress uses PHPDoc for adding documentation to code. PHPDoc is a standard for documenting files, functions, classes, and any other code written in PHP. The following is an example of using PHPDoc to document a function:

<?php
/**
 * Short Description.
 *
 * Longer and more detailed description.
 *
 * @param  type  $param_a  Description.
 * @param  type  $param_b  Description.
 * @return type            Description.
 */
function pdev_function( $param_a, $param_b ) {
       // Do stuff.
}

As you can see, the inline PHPDoc describes what the function does, what parameters it accepts, and what it returns. Another developer wouldn't even have to read your code to understand what it does.

Naming Variables and Functions

Variables and functions should always be written in snake case. All characters should be written in lowercase, and multiple words should be separated with an underscore. Functions and variables in the global namespace should also be preceded with a unique prefix for your plugin, such as pdev_. The following example is the correct way to write a function:

<?php 
function pdev_function( $param_a ) {
        // Do stuff.
}

$param_a isn't in the global scope there, so it doesn't need a prefix. While it's considered bad practice to use global variables, if you do use them, make sure to prefix.

Naming Classes and Methods

Class and method naming is one area where the core WordPress coding standards don't align with the PHP community. The PHP standard is to write class names in PascalCase where the first character of each word is uppercase and there are no separators between words. The standard for class methods is to write words in camelCase where the difference is that the first character of the first word is lowercase.

The following example shows what a basic class with a single method looks like using this method:

<?php
 
class PDEVSetup {
 
        public function setupActions() {
        }
}

The WordPress coding standards follow a different set of rules. Look at the following example to spot the differences:

<?php
 
class PDEV_Setup {
 
        public function setup_actions() {
        }
}

As you can see, the WordPress method uses underscores to separate class names and uses snake case for method names. You'll need to decide the best direction for your own plugins. There's no one right answer, and developers have been arguing over naming schemes for as long as programming has existed. The most important thing is to be consistent in your own code.

Naming Files

WordPress has a strict guideline on how it names files. The standard is to write each character in lowercase and separate multiple words with hyphens. For example, you might have a group of user‐related functions in your plugin. You'd want to name that file something like functions‐users.php.

WordPress also prefixes class filenames with class‐. The PDEVSetup or PDEV_Setup class from the previous section in this chapter would be named class‐pdev‐setup.php following the WordPress standard.

Again, this is where WordPress deviates from the standards within the PHP community. At some point, you'll likely want to use an autoloader, such as the one provided by Composer (https://getcomposer.org). Once you do that, you'll quickly realize that the best method of naming class files is for the filename to match the class name exactly because it simplifies the autoloader code and keeps you from having to write a custom implementation. In this case, you should name the file for the PDEVSetup class as PDEVSetup.php.

Single and Double Quotes

PHP allows you to use single or double quotes when defining strings. With WordPress, it's recommended to always use single quotes when possible. This makes it easy to use double quotes within the string without escaping them. The following is an example of echoing a link that has double quotes within the single‐quoted string:

<?php 
echo '<a href="https://example.com">Visit Example.com</a>';

You can also use double quotes when you need to insert a variable within the string. The following example grabs the current site's name and echoes a message with the variable:

<?php
$pdev_site_name = get_bloginfo( 'name', 'display' );
echo "You are viewing {$pdev_site_name}.";

Indentation

Put 10 programmers in a room and pose the question, “Spaces or tabs?” This may be the closest you'll ever see to a programming discussion resulting in fisticuffs. Many a developer has lived and died on their personal space/tab hill. The one thing that most can agree on is that your code should follow some sort of standard indentation.

The WordPress standard is to indent all code with tabs. Consider the following example of an if/else statement:

<?php
if ( $condition ) {
echo 'Yes';
} else {
echo 'No';
}

It's hard to follow the logical structure of the code with no indentation. Instead, you should indent each line within the brackets of the conditions, as shown in the following example:

<?php
if ( $condition ) {
       echo 'Yes';
} else {
       echo 'No';
}

The one exception that WordPress makes to its tab preference is when aligning multiple lines of similar items. Take note of the spacing usage in the following snippet:

<?php
$some_var        = 'ABC';
$another_var     = 'JKL';
$yet_another_var = 'XYZ';

As you can see, the operators and values assigned to the variables are clearly lined up and easy to read.

Brace Style

Any multiline statement in PHP should use brackets to contain the entire code block. Following this brace style will keep your code clear and less prone to errors. See the next code snippet for the appropriate usage of braces:

<?php
if ( $condition_a ) {
       action_a();
} elseif ( $condition_b || $condition_c ) {
       action_b();
       action_c();
}

Even if there's only a single line within each block, make sure to enclose it too. Forgoing the braces for single‐line statements is usually a bad idea and may result in bugs when you add extra code in the future.

Space Usage

When building your plugin, you should always add spaces after commas and on each side of logical, comparison, and other operators. The following code snippet shows several basic PHP examples and how they should be spaced:

<?php
if ( $foo === 'bar' ) {
        // Do something.
} elseif ( ! $foo ) {
        // Do something else.
}
 
foreach ( $foo as $bar ) {
        // Do something.
}
 
function pdev_function( $param_a = 'foo', $param_b = 'bar' ) {
        // Do something.
}
 
$foo = range( 10, 100, 10 );

Using this spacing technique keeps your code clean and makes it easy to read. The rule of thumb is to always be judicious with spacing. Or, when in doubt, use a space.

Shorthand PHP

You should never use shorthand PHP tags ( <? and ?>) when developing plugins. Shorthand tags must be enabled on the server to work. As a plugin developer, you typically won't have access to the server, so there's no guarantee they'll work for your users. Always use the full PHP opening and closing tags ( <?php and ?>).

The one exception to this rule is for the short echo tag, as shown in the following example:

<?= 'Hello, World!'; ?>

The short echo tag is always enabled as of PHP 5.4. This is uncommon usage and not standard for WordPress. It's typically used in templates, which is not the primary use case for plugins.

SQL Statements

When writing SQL statements in WordPress to make a direct database call, always capitalize the SQL part of the statement. Most statements should be written on a single line, but it's OK to break the statement into multiple lines if the statement is complex.

SELECT ID FROM wp_users WHERE user_login = 'example'

Chapter 4, “Security and Performance,” covers how to create proper SQL statements in more detail.

SUMMARY

This chapter covered how to properly set up your WordPress plugin. Following the methods and techniques outlined in this chapter will set you on the path to building plugins professionally. Starting from a solid foundation by following coding standards and documenting your code will make it easier to maintain your plugin in the long term. It will also help other developers understand your code. It's important to get the foundation right before moving on to more advanced topics.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.66.13