How I write my WordPress Plugins with Classes

One of the things I’ve always hated about WordPress is writing larger plugins with lots of functions and global variables. While it isn’t always possible to write a wordpress plugin using OOP techniques that would satisfy an OOP purist, it is possible to make things a little cleaner and easier to extend and maintain for yourself.

Update: This way of using classes is not a pure OO way of designing a plugin, it’s mainly a way of namespacing your code and keeping as much as possible out of the global namespace. I’ll write a post in future detailing some of the concepts I now use for writing plugins such as using php 5.3 namespaces and using real OO design in my plugins.

The following tutorial is for php 5+ and outlines a basic structure for an object orientated wordpress plugin. You could take these examples as far as you want, however at some point you will have to decide between speed, flexibility and design.

I say this because I believe you can reach a happy medium between writing wordpress plugins and using classes. Sure it will not strictly adhere to standards that you may be used to using but you will have to directly call core wordpress core functions eventually.

I choose not to introduce extra layers of functionality by wrapping core wordpress variables like wpdb and instead use them in my class methods by a global variable. This is not pretty and not to standards, but I choose this over wrapping all of the wordpress core and slowing down my applications, also this is the wordpress way.

If you have suggestions or improvements, please leave a comment. Without further ado, here is a basic shell wrapper for a plugin. (zip file at end of article).

my-plugin/my-plugin.php

This is the main WP plugin file. It chooses which main class (admin or public) to initialize by checking the wordpress function is_admin. This allows us to keep admin plugin code and code that runs on the public site separate.

[crayon lang=”php”]

/*
Plugin Name: My Plugin
Description: How to design a plugin with classes
Version: 1.0
Author: Greg F
Author URI: http://www.gregfreeman.io
*/

define( ‘MY_PLUGIN_PATH’, dirname( __FILE__ ) );
define( ‘MY_PLUGIN_URL’, plugins_url( ”, __FILE__ ) );
define( ‘MY_PLUGIN_FILE’, plugin_basename( __FILE__ ) );
define( ‘MY_PLUGIN_INC’, MY_PLUGIN_PATH . ‘/inc’ );

require_once( MY_PLUGIN_INC . ‘/plugin.php’ );
require_once( MY_PLUGIN_INC . ‘/config.php’ );

$my_class = ‘My_’;

if ( is_admin() ) {
$my_class .= ‘Admin’;
require_once( MY_PLUGIN_INC . ‘/admin.php’ );
} else {
$my_class .= ‘Public’;
require_once( MY_PLUGIN_INC . ‘/theme-functions.php’ );
require_once( MY_PLUGIN_INC . ‘/public.php’ );
}

$my_config_data = array(
‘plugin_file’ => MY_PLUGIN_FILE,
);

$my_plugin = new $my_class( new My_Config( $my_config_data ) );

unset( $my_class, $my_config_data );

[/crayon]

my-plugin/inc/plugin.php

This is the base class that admin and public extend. It makes the config class available to both subclasses and has two methods for plugging into WP filters and actions. It also calls an init function that is used by admin and public to setup filters and actions.

All of your filter/action calls should go into the init method in My_Admin or My_Class.

[crayon lang=”php”]

abstract class My_Plugin {
protected $_config;

public function __construct( My_Config $config ) {
$this->_config = $config;

$this->init();
}

abstract protected function init();

protected function add_action( $action, $function = ”, $priority = 10, $accepted_args = 1 ) {
add_action( $action, array($this, $function == ” ? $action : $function ), $priority, $accepted_args );
}

protected function add_filter( $filter, $function, $priority = 10, $accepted_args = 1 ) {
add_filter( $filter, array($this, $function == ” ? $filter : $function ), $priority, $accepted_args );
}
}

[/crayon]

my-plugin/inc/config.php

This is a basic wrapper for config variables, in this example it stores things like the base plugin path and file. In your plugin it could wrap wordpress options and calls to get_option.

[crayon lang=”php”]

class My_Config {
protected $config;

public function __construct( array $config ) {
$this->config = $config;
}

public function __get( $name ) {
$value = false;
if ( array_key_exists( $name, $this->config ) ) {
$value = $this->config[$name];
}
return $value;
}
}

[/crayon]

my-plugin/inc/admin.php

Here is the admin class. In this example it registers the activation hook. See the public class below for more ways to use this setup.

In My_Admin you will normally have filter/action calls to admin_init, save_post, add_meta_boxes etc. You can use the wordpress settings_api inside of your admin_init method.

[crayon lang=”php”]

class My_Admin extends My_Plugin {
protected function init() {
register_activation_hook( $this->_config->plugin_file, array( $this, ‘activate’ ) );
}

public function activate() {
// plugin activate code
}
}

[/crayon]

my-plugin/inc/public.php

The public class has everything that is needed for the frontend site. In this example (commented out) It adds a filter for pre_get_posts which adds a custom post type to all queries on the frontend. A second function called say_hello is created to perform a basic greeting.

[crayon lang=”php”]

class My_Public extends My_Plugin {
protected function init() {
//$this->add_filter( ‘pre_get_posts’, ‘set_post_types’ );
}

public function set_post_types( $query ) {
$query->set( ‘post_type’, array( ‘post’, ‘my_custom_post_type’ ) );

return $query;
}

public function say_hello( $name = ” ) {
$greeting = ‘hello’;
if( $name ) {
$greeting .= ‘ ‘ . esc_attr( $name );
}

echo $greeting;
}
}

[/crayon]

my-plugin/inc/theme-functions.php

Theme functions holds all of the functions that are called on templates. Instead of calling $my_plugin->say_hello( ‘greg’ ); ?> in your theme, you can type my_say_hello( ‘greg’ ); instead. This is optional and is only included to avoid typing additional characters that may be unfamiliar to designers etc.

[crayon lang=”php”]

function my_say_hello( $name = ” ) {
global $my_plugin;
$my_plugin->say_hello( $name );
}

[/crayon]

I hope this helps you with your wordpress plugin classes! Using this setup, your plugin only creates one global variable called $my_plugin in the my-plugin/my-plugin.php file. The other major advantages is the ability to ‘hide’ code using protected/private variables and methods. This allows you to stop normal wordpress users from calling internal functions and restricts them only to your public facing ‘API’.

Let me know if you have suggestions.

Download my-plugin.zip

, ,

2 thoughts on “How I write my WordPress Plugins with Classes

  • Uzo says:

    Looks like a pretty airtight way to ensure your functions are not accidentally triggered or clashing. Definitely got a lot of improvements to make in how I’ve been structuring functions and whatnot.

    Very lovely tips. Thanks for sharing!

  • Pankaj Kumar says:

    Can you please suggest me a book which provides wordpress plugin development using classes in object oriented way.

Leave a Reply

Your email address will not be published. Required fields are marked *