The Publishing Project

Additional considerations for OOP plugin development

Rather than writing plugins (or any PHP code) procedurally, we can leverage Object-Oriented Programming (OOP) to write our plugins. OOP is easier to maintain and extend as the needs of the plugin increase.

The code below is a good starting point for class-based plugins. It doesn’t have the full plugin comment but the code should still work (even if it does nothing yet).

<?php
if ( ! class_exists( 'AwesomePlugin' ) ) {
  class AwesomePlugin {

    /**
     * Constructor
     */
    public function __construct() {
        $this->setup_actions();
    }

    /**
     * Setting up Hooks
     */
    public function setup_actions() {
        //Main plugin hooks
        register_activation_hook(   
          __FILE__, 
          array(
            'AwesomePlugin',
            'activate'
          )
        );
        register_deactivation_hook(
          __FILE__,
          array(
            'AwesomePlugin', 
            'deactivate'
          )
        );
    }

    /**
     * Activate callback
     */
    public static function activate() {
        //Activation code in here
    }

    /**
     * Deactivate callback
     */
    public static function deactivate() {
        //Deactivation code in here
    }      
}

  // instantiate the plugin class
  $wp_plugin_template = new AwesomePlugin();
}

Constructor differences

One thing that tripped me several times is the difference when working with class methods inside the class. Rather than referencing the methods directly, you must use an array syntax:

<?php
    register_activation_hook(
      __FILE__,
      array(
        'AwesomePlugin', 
        'activate'
      )
    );

In a normal filter or hook declaration, the second parameter is just the name of the function we want to use as the callback. When working with classes we must use the array syntax.

Visibility Modifiers And The Static Keyword

as you start planning your plugin you might want to consider who can see the code inside your classes. PHP provides the three traditional visibility modifiers: public, protected, and private. The table below shows how they work.

Modifier Description
public Allows access from anywhere
protected Allows access from Class parent and subclasses
private Allows access from Class only

There’s another modifier for class methods and properties: static.

The static keyword allows access to the method or property without having to instantiate the class.

<?php
class Foo {
  public static function aStaticMethod() {
    echo 'Inside aStaticMethod';
  }
}

Foo::aStaticMethod();
$classname = 'Foo';
$classname::aStaticMethod();

Composer or no Composer

Composer is a dependency manager for PHP, similar to what NPM does for Node.js or Bundler does for Ruby Gems.

There are two reasons why I would use Composer in a project:

  • I have external dependencies
  • I want classes and libraries, both local and installed with Composer, to autoload

Using composer requires a slightly different approach to writing plugins. We first need to run composer init, and answer the questions it asks, to create the project’s composer.json file and the necessary directories.

Then I change the location of third-party libraries in composer.json and run composer install to install the libraries in their new location.

{ 
  "config": { 
    "vendor-dir": "lib/" 
  } 
} 

The final step to get a plugin ready to use Composer autoload is to add the following statement to the main class file:

<?php
require __DIR__ . '/lib/autoload.php';

Whether you need to use Composer or not is a matter of personal preference and the project’s complexity

Embracing Complexity

Coming from Javascript it’s always tempting to write all the code for a project in a single file. For some small projects, that’s OK, but for larger projects, it may not be.

It’s OK, and sometimes it’s considered a best practice, to break the project into a set of components, each living on its own file.

require and require_once allow you to load a file from the file system.

Using Composer (as discussed earlier) allows you to load files and external libraries using the autoloader.

It’s worth considering the complexity and the number of files you expect to have in your project as you’re getting started. Adding Composer from the start may save you many headaches later on.

PHPDoc is your friend, use it

Documenting the code is a good practice and can help you down the road. If you’re working on a team and need to onboard people, having document comments in your code will make it easier for the new teammates to get up to speed. another instance where commenting the code is useful is when you leave your project for a while and then have a hard time remembering what it did or how it’s supposed to work.

PHPDocumentor) is a combination of comment styles (DocBlocks) and a parser that will generate documentation from the comments on your code.

A DocBlock is a piece of documentation in your source code that informs you what the function of a Structural Element is.

phpDocumentor follows the PHPDoc definition and recognizes the following Structural Elements:

  • Function
  • Constant
  • Class
  • Interface
  • Trait
  • Class constant
  • Property
  • Method

In addition to the above, the PHPDoc standard also supports DocBlocks for Files and include/require statements, even though PHP itself does recognize this as a language structure.

Each of these elements can have exactly one DocBlock associated with it, which directly precedes it. No code or comments may be between a DocBlock and the start of an element’s definition.

WordPress uses a customized version of PHPdoc to annotate the source code. Documentation in WordPress mostly takes the form of either formatted blocks of documentation or inline comments.

The following is a list of what should be documented in WordPress files:

  • Functions and class methods
  • Classes
  • Class members (including properties and constants)
  • Requires and includes
  • Hooks (actions and filters)
  • Inline comments
  • File headers
  • Constants

Where the core PHPDoc documentation and the WordPress Documentation Standards disagree, the WordPress Documentation Standards take precedence.

Note:

This conversation is only applicable to PHP. If you’re working with Javascript, check the JavaScript Documentation Standards and JSDoc 3 Standard for more information.