Should all plugins be encapsulated in a Class?

When developing a plugin should the functions be grouped together into a Class to avoid namespace conflicts?

Does using classes create performance overheads for PHP?

Read More

If there is a performance hit, should function names just be pre-fixed instead?

Related posts

Leave a Reply

5 comments

  1. When developing a plugin should the functions be grouped together into a Class to avoid namespace conflicts?

    Yes, but that’s only one of the minor arguments. In-fact that’s not the “true” nature of a class in OOAD.

    Does using classes create performance overheads for PHP?

    No, not notably. Bad design and/or bad written code or pre-mature optimisation creates far more performance problems than actual language features.

    If there is a performance hit, should function names just be pre-fixed instead?

    As written, there is no performance hit. Bad written code will be more of a performance hit than good written code that has some more lines of code but does not force you to do bad things.


    Bottom Line:

    You can make differently use of classes for plugins. You can just use them to have some kind of namespace and use them “just” for global functions. The most direct form of that are static class functions, the following code-example shows both, first global functions, then global static class functions:

    /* global function */
    function myplug_hook()
    {
    }
    
    add_filter('the_hook', 'myplug_hook');
    
    
    /* global static function */
    class myplug
    {
        public static function hook()
        {
        }
    }
    
    add_filter('the_hook', 'myplug::hook');
    

    This is just a little example showing that you need to type more for the single hook. Additionally it shows how the namespacing works: You can easier replace the single class name to rename all static functions and then search and replace myplug:: which could be harder with myplug_ because of false positives. But in the end there is not much difference.

    The key point is: static class functions Docs are not really much else then global functionsDocs.

    And this example shows as well: Namespacing is fine, but with worpdress, the namespacing stops with using hooks: The callback function is hardencoded, hence the benefit in namespacing using the class (one place for the base-name, the classname) does not help when you intervene your code with wordpress for the hook names.

    The real benefit starts with using actual class instances and non-static functions. This has the benefit that you can start to make use of OO principles and you can streamline your code. Static class functions are more a problem than a solution infact.

    Then it’s more than just syntactic sugar.

    Key point is: Do something that helps you to write the code you can easily deal with and maintain. Don’t over-rate performance, that’s a common mistake. More important is that you write code that is easy to read and understand, that just does what you need. Maybe this question and answer is helpful for a bigger picture in this context: Multiple Custom Metabox Help.

    One common approach I have even with smaller plugins is making use of a static helper function to instantiate the plugin and the rest resides within the plugin instance then. This helps to encapsulate the main plugin logic and it benefits from namespacing with the hooks as well that private members can be re-used between hooks which is not possible with standard global functions. The following code-example shows the pattern:

    <?php
    /** Plugin Headers ... */
    
    return MyPlugin::bootstrap(); 
    
    class MyPlugin
    {
        /** @var MyPlugin */
        static $instance;
        static public function bootstrap() {
            if (NULL === self::$instance) {
                self::$instance = new __CLASS__;
            }
            return self::$instance;
        }
        # ...
    }
    

    This is a common pattern I use for the base plugin file. The plugin class on the one hand represents the plugin to wordpress and on the other hand it allows to start to use object oriented paradigms for the own code which can even be completely object oriented (but need not be). It’s kind of a controller, interfacing with the whole wordpress API as the request(s).

    As the example shows, an instance of the plugin will be created. This allows you to make use of known commons like a Constructor Docs (__construct) to initialize the actual plugin:

    # ...
    class MyPlugin
    {
        # ...
        public function __construct()
        {
            add_filter('the_hook', array($this, 'hook'));
        }
    
        public function hook()
        {
        }
        # ...
    }
    

    At the time the hook is registered, this plugin object already benefits from it’s design: You’ve ceased to hard-code the actual hook function against the concrete plugin classname. That’s possible because of the binding of the class to the object instance for the callback. Sounds complicated, just saying: $this is the plugin. Can be used in hook callbacks, compare Registering Class methods as hook callbacks.

    This pattern allows to easier interface with wordpress: the injection is reduced to the names of the hooks and which data they provide. You can then start to implement directly into this plugin class or to refactor your implementation against it, so to only put code into the plugin class that is the bare minimum to define your plugins interface against wordpress, but keep the general logic aside of worpdress. This is where the fun starts and most probably that what each plugin author want’s to achieve in the long run.

    So don’t program with worpdress but against it. As worpdress is quite flexible, there is no common or easy to describe interface to program against. A base plugin class can take up this role, allowing you more flexibility for your own code which will lead to easier code and a better performance.

    So there is more than just a benefit for name-spacing. Best suggestion I can give is: Try yourself. There is not much you’ll loose, only new things to discover.

    You’ll most probably notice differences after you’ve passed some more major updates of wordpress while keeping your plugin compatible.

    Caveat: If your plugin directly integrates with wordpress to get the job done, using one or two public functions might suit you better. Take the right tool for the job.

  2. Classes VS function set


    Performance

    General: Afaik, there’s no difference in “performance” between classes and function
    sets.

    Detail:

    • There’s a big difference if you question function_exists() vs. class_exists() as normally you got a lot of functions (~1.800(?) in wp core) vs. classes ( ~100(?) in wp core). So making stuff “pluggable” and therefore questioning the existance is a difference in execution time.
    • Classes offer one big advantage over function sets: You can much easier avoid calling it on a request where you don’t need it, then with functions. You only have to do conditional checks for the class and not for every function. So if you don’t need it on every page load and can avoid calling lots of if/else statements, a function “performs better”.

    Architecture – How stuff works:

    function set: In general, functions gets executed in the row you call it. So every time you call stuff, you have to write it again, if you have to call it more than once.

    Class: There are different aproaches to classes. The class, that comes closest to a function set is the “factory” class (wikipedia/google). Imo it’s nearly the same as a set of functions, but encapsulated in a class. But there are other “types” of classes too. You could for example write an abstract or a parent class class, that you extend with a child class. In a real world example: Let’s say you got a class that builds some static text fields. In your __construct() function you have a set of scenarios like “left_column”, “right_column” & “footer_field”. Then you call something like $text_field = new TextFieldClass(); to instantiate the class. And later you simply call $text_field->add( $case => 'left_column', 'case' => 'foo text' ); and $text_field->add( $case => 'footer_field', 'case' => 'bar text' );. Then all your conditionals and else have already been performed when you instantiated the class and just the two class functions would have been called when you build the text fields. In this szenario you could have saved some ms of execution time.


    Personal Opinion

    If you write your classes wisely, then you’ll have a minor advantage in performance. But you’ll have a well organized structure to work on. So far nothing spectacular. But if you consider the following “split” use cases for classes and functions in a plugin, then you’ll get my final point: Class is internal, functions are API. As long as you offer API only via publicly useable functions (that then call classes or class functions), you’ll be on the save side developing your plugin further. You acchieved the freedom to change the internal structure or even the possibilities of your plugin without affecting the users anytime and everywhere.

    Example:

    // construction of object
    if ( ! class_exists( 'WPSE_HelloWorld' ) )
    {
    
    class WPSE_HelloWorld
    {
        function __construct( $args = array( 'text', 'html', 'echo' ) )
        {
            // call your object building procedures here
            $this->hello_world( 'text', 'html', 'echo' );
        }
    
        function hello_world( 'text', 'html', 'echo' )
        {
            $start_el = '<{$html}>';
            $end_el = '</{$html}>';
            if ( $echo )
            {
                return print "{$start_el}{$some}{$end_el}";
            }
    
            return "{$start_el}{$some}{$end_el}";
        }
    } // END Class 
    
    }
    
    // API: public functions
    function the_hello_world( $args( 'echo' => true ) )
    {
        $new = new WPSE_HelloWorld();
        return $new->hello_world( $args );
    }
    
    function get_hello_world( array( $args( 'echo' => false) ) )
    {
        $new = new WPSE_HelloWorld();
        return $new->hello_world( $args );
    }
    
    // then you can call it like get_the_title() or the_title(), which you know from the WP API:
    // 'echo' is set to false per default:
    $some_var = get_hello_world( array( 'text' => 'hello reader', 'html' => 'strong' ) );
    # *returns* "<strong>hello reader</strong>"
    
    // 'echo' is set to true per default:
    the_hello_world( array( 'text' => 'hello reader', 'html' => 'strong' ) );
    # *prints/echos* "<strong>hello reader</strong>"
    

    Note: Please also read the link @t310s posted in the comment to the Q.

  3. Classes don’t usually offer any benefits in terms of performance, but they very rarely have any negative effects either. Their real benefit is in making the code clearer and avoiding namespace conflicts.

  4. Most of the time, if you use functions, you’ll put the name of the plugin in each function name, so effectively, you’ll duplicate that name a dozen times if the plugin has a dozen functions which is a bit of a drag.

    With classes, you’d just have the name of the plugin in the class name likely once.

    Additionally, you can use inheritance or other oo constructs to implement behaviors in a very clean manner. Here is an ex:

    class animalplugin{
      //plugin functions...
      function talk(){print "animalnoise";}
    }
    class animalplugin_with_cat_mods extends abcplugin{
      //cat functions overrides
      function talk(){print "meow";}
    }
    if (iscat()){
      new animalplugin_with_cat_mods();
    } else {
      new animalplugin();
    }