Tag Archives: php

How and why to write Object Oriented WordPress plugins

Today I want to discuss an object oriented approach to plugin design that works no matter how small or large your plugin is going to become. Once I started doing this, I found it very difficult to return to the old way.

WordPress is… ahem… a “mature” codebase. It’s strength is not necessarily in its modern, lightweight design, but instead in its broad user base and ease of use. These two things are somewhat at odds, given how quickly programming languages evolve.

WordPress is fully compatible with PHP 5.2.9, which means that someone who set up a website 7 years ago at a cut-rate web host, will still get security updates, and, as of now, can still update WordPress to experience the latest and greatest core offerings (although maybe not the latest and greatest plugins) with no issue.

What’s changed between PHP 5.2.9 and now?

  • Introduction of Interfaces
  • Introduction of Namespaces
  • Anonymous functions
  • Anonymous classes

These are just to name a few.

And although PHP 5.2.9 does allow basic but solid object oriented programming techniques, WordPress has a developed enough codebase that a lot of WordPress is built with functions and global variables.

I don’t think you should follow their lead.

To illustrate the difference between the old “WordPress” way, and the new Object-Oriented way (which, in fairness, WordPress implements in many of its newer classes), take a look at these two code samples which do the same thing:


// Procedural
<?php
add_action('init', 'my_long_unique_hello_world_function');
function my_long_unique_hello_world_function() {
    echo "Hello World!";
    die();
}

add_action('admin_init','my_long_unique_admin_hello_world_function');
function my_long_unique_admin_hello_world_function() {
    echo "Hello Admin!";
    die();
}

// OOP
<?php
class My_Unique_Class {
    public function load() {
        add_action('init', array($this, 'init'));
        add_action('admin_init', array($this, 'admin_init'));
    }

    public function init() {
        echo "Hello World!";
        die();
    }

    public function admin_init() {
        echo "Hello Admin!";
        die();
    }
}

global $my_unique_class;
$my_unique_class = new My_Unique_Class();
$my_unique_class->init();

At first glance, the second example is much more verbose, so it’s probably a load worse, right? Granted, for an example with only one action hook, this is overkill. But most plugins do not have just one action hook. Most plugins have several.

And when you get to several action hooks, this becomes really, really helpful.

First of all, rather than having to write a very long function name for your action, you can often write exactly what it is. For example, in my classes, I try to add one function per action per class, so that the init hook always points to the class::init() method. This can make it easier for me to track down coding issues.

Second of all, you may have noticed my little global at the bottom. Because WordPress hasn’t offered a better solution, this is still unavoidable. However, it still dramatically reduces the amount of pollution many plugins would cause in the global scope. Remember, each function outside of a class is also part of the global scope! That increases the likelihood of collisions with other plugins.

Third, this allows you to make full use of object scoping, making things private and protected for internal use only. This may not seem like a big deal, but it can do wonders to remove your dependency on global variables. I’ve used this to build a number of plugins, a good example of which is a footnotes plugin, where each [cite] shortcode is added to a class property and printed as needed (Gist here). Is it strictly necessary to use classes to make something like this work? No. Does it make it a lot easier and dramatically reduce the chance for collisions? Yes!

There’s a lot more to love about Object Oriented programming, including Interfaces, Namespaces, and much more. I’m going to be diverging from the WordPress world to cover some of these concepts, but they should still apply pretty easily. Stay tuned!

How To Install Composer programatically

If you want to automate the download and installation of Composer, chances are you are trying to figure out how to install Composer programatically. For example, I have a setup at work where I have an install script to create local developer environments in vagrant, which includes Composer. The fatal mistake is copying the Composer download script directly from the website. The reason for this is that the signature regularly changes as the software updates, and Composer downloads with a hard coded signature will fail. Fortunately, Composer offers a very easy way to verify signatures programatically.

To use it in Linux, you can substitute the signature string with:

$(curl -Ss https://composer.github.io/installer.sig)

The full syntax:

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('SHA384', 'composer-setup.php') === '$(curl -Ss https://composer.github.io/installer.sig)') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"

The end result of this is that you can install composer on a new machine without having to constantly check the signature on the web.

This is useful if you need a script, or just want a simple executable that downloads and installs Composer without having to visit the web page every time.

Installing PHPBrew with VVV

VVV is awesome. For all its very impressive features, there are some things it doesn’t do (yet). One of those is run PHP 5.6, or PHP 7 (or, while we’re at it, older versions like PHP 5.3). PHPBrew makes this a walk in the park. If, that is, you use the right configurations and install the correct dependencies. I had a hard time finding a good step-by-step guide detailing missing dependencies and configuration options needed for PHPBrew. I’ve put one here to save others (and myself in the future) some time. And for those curious, many of these steps are helpful when installing on any Ubuntu dev server, not just VVV or WordPress.

Without further ado:

A Walkthrough for Installing PHPBrew on VVV

1. Install Dependencies

This was one of the most annoying things to discover. Every time I tried to install PHPBrew, it failed with a missing dependency.

On VVV, you can install these dependencies with the following command:

sudo apt-get install libxml2-dev libbz2-dev libmcrypt-dev libxslt-dev

2. Download & Install PHPBrew

Install PHPBrew using their recommended fashion (at least, as of March 2016, when this is written):

curl -L -O https://github.com/phpbrew/phpbrew/raw/master/phpbrew
chmod +x phpbrew
sudo mv phpbrew /usr/local/bin/phpbrew

And, as Lance Cleveland mentions in the comments, you should also type in:

phpbrew init

When this is complete, you can review available versions with phpbrew known. Here you will see a list of PHP versions, new and old. For example, I spotted the latest available version on phpbrew (again, as of March 2016), and installed it with options that are required for WordPress and VVV’s server configuration (note: cli is not strictly required, but I installed it so I could use WP-CLI):

phpbrew install 5.6.19 +default +fpm +mysql +cli

You can add other options, like +curl, for example.

Then, switch. I received a message which gave me a command that didn’t work, so here is the one that did:

phpbrew switch 5.6.19

Or whichever version you are installing.

3. (Optional) Install extensions

If you’re looking for xdebug, a feature that comes standard on VVV but gets overwritten with a new version of PHP, you can add the extension with:

phpbrew ext install xdebug stable

You can install APC and Memcache similarly, if you need to test it.

If you’re looking for any additional configuration options, there are a good number, as well as some helpful hints. These are not WordPress specific, so rather than try to copy them all, take a look at PHPBrew‘s web page, which has a lot of documentation.

I hope this helps you as much as it would have helped me when beginning my PHPBrew adventure.

Addendum

For a non-VVV server install, I needed to include these dependencies for Ubuntu as well when I installed PHP 5.3:

sudo apt-get install libreadline-dev libicu-dev