Initialize a plugin with a configuration object

The WordPress plugin API, based on actions and filters called in a certain order, forces plugin authors to follow a simple rule to guarantee interoperability: Whatever you do, offer a way to turn it off.

If your plugin uses a code like this …

add_action( 'wp_loaded', 'my_callback' );

… other plugins or a theme can turn it off with …

remove_action( 'wp_loaded', 'my_callback' );

This won’t work with objects:

    array ( new Plugin_Object, 'setup' ) 

Another plugin has no access to the object, so it will be very difficult to remove this callback.

There are two solutions for this problem: static access to the instance of the main class and a filter for a configuration object.

Static access to plugin instance

An example for the first solution can be found in this gist. Basically, we don’t use new Plugin_Object, but new Plugin_Object::get_instance() to create the object.

public static function get_instance()
	NULL === self::$instance and self::$instance = new self;

	return self::$instance;

Initialization works like this now:

	array ( Plugin_Object::get_instance(), 'setup' )

This works, and it has become quite popular. But I never liked the static method. The only benefit is an on/off option, the ability to stop a plugin. But what if we want to change just some part of the plugin without disabling it completely? We had to add some actions and filters, more and more probably. I think this is not very elegant.
That’s why I prefer a configuration object filter now.

Configuration object filter

In this structure, the main controller object will be created always. But, as the term controller already suggests, it is just a light-weight object with one job: sticking other objects together.

namespace Wpkrauts;

class Controller
    protected $plugin_file;

    public function __construct( $file )
        $this->plugin_file = $file;

        \add_action( 'wp_loaded', array ( $this, 'plugin_setup' ) );

    public function plugin_setup()
        $data = new \stdClass;
        $this->set_plugin_data( $data );

        // class names
        $data->model   = __NAMESPACE__ . '\Plugin_Log_Data';
        $data->view    = __NAMESPACE__ . '\Console_Live_Logger';

        /* You can change the class names here, the new classes have just to
         * implement the interfaces.
         * Or set "$data->stop" to TRUE in the filter to stop further processing.
        \apply_filters( 'wpkrauts_base_plugin_data', $data );

        if ( ! empty ( $data->stop ) )

        $model = new $data->model( $data );
        $view  = new $data->view( $model );

            array ( $view, 'show' )


    protected function set_plugin_data( $data )
        $data->url     = \plugins_url( '', $this->plugin_file );
        $data->dir     = \plugin_dir_path( $this->plugin_file );
        $plugin_info   = \get_file_data(
            array (
                'name'    => 'Plugin Name',
                'version' => 'Version'
        $data->name    = $plugin_info['name'];
        $data->version = $plugin_info['version'];

As you can see I separated the plugin code by following a MVC structure. Plugin_Log_Data and Console_Live_Logger are the model and the view. Both implement simple interfaces:

interface Log_Data
    public function __construct( \stdClass $data );

    public function get_value( $name );

interface Live_Logger
    public function __construct( Log_Data $model );

    public function show();

The actual implementation in my sample case logs the plugin data to the browser’s JavaScript console.

Screenshot of the result in a console

class Plugin_Log_Data implements Log_Data
    protected $data;

    public function __construct( \stdClass $data )
        $this->data = $data;

    public function get_value( $name )
        if ( isset ( $this->data->$name ) )
            return $this->data->$name;

        return new \WP_Error(
            "Invalid name: $name",

class Console_Live_Logger implements Live_Logger
    protected $model;

    public function __construct( Log_Data $model )
        $this->model = $model;

    public function show()
            '<script>console.log( \'%1$s\nVersion: %2$s\n%3$s\' );</script>',
            $this->get_js_var( 'name' ),
            $this->get_js_var( 'version' ),
            $this->get_js_var( 'bogus' ) // error demo

    protected function get_js_var( $var )
        $text = $this->model->get_value( $var );

        if ( is_wp_error( $text ) )
            return "ERROR: " . esc_js( $text->get_error_message() );

        return esc_js( $text );

This might not be the most useful example, but I hope it is easy to understand.

Now let’s go back to the controller. There is an important line:

\apply_filters( 'wpkrauts_base_plugin_data', $data );

Since object variables are passed as an identifier in PHP we don’t even need a return value from the filter. You can change it in a custom additional function, and these changes will be applied immediately.

To stop further execution of my plugin you can do this:

\add_filter( 'wpkrauts_base_plugin_data', function( $data )
    $data->stop = TRUE;

Dead simple, almost too trivial.

But you can do much more:

All of this and probably more is possible with just one single filter. No static methods are needed anymore.

The configuration object I have used here is a simple stdClass. This is not ideal, and when you need a copy it might become expensive. I will show an alternative in a later article.

You can find all code examples for this article on GitHub.


Web developer since 1998, moderator on WordPress Stack Exchange, author, manic reader.

Code is my drug.

Find Thomas Scholz on⁠, ⁠, ⁠, ⁠, ⁠, ⁠, and .


  1. webaware29.07.2013 01:45

    From the other direction, if you need to remove hooks to objects that don’t have globals you can easily access, you can loop over $wp_filter and check for the objects to remove their filters. See function removeObjectFilters() on this blog post:


  2. Leho Kraav (@lkraav)25.08.2013 09:38

    So the minimum PHP requirement for this approach is 5.3, yes?


  3. David – 05.09.2013 14:06

    I guess i have to try this approach to find all pros and cons. What I see now is, that it might become a very time-consuming implementation whith larger plugins where you will have more than one model, one view and one controller.

    What is a proper way to make basic attributes (like VERSION) available to other objects? Dependency injection?


Leave a Reply

Your email address will not be published.