Autoloading of Classes

Discussions and requests related to new CMSimple features, plugins, templates etc. and how to develop.
Please don't ask for support at this forums!
Post Reply
cmb
Posts: 14225
Joined: Tue Jun 21, 2011 11:04 am
Location: Bingen, RLP, DE
Contact:

Autoloading of Classes

Post by cmb » Tue Oct 21, 2014 12:34 pm

Hello Community,

dropping PHP 4 support for CMSimple_XH 1.7 is already under discussion. There are several improvements that would be possible then. One of these is autoloading of classes (available since 5.0.0 resp. 5.1.2). The benefits of autoloading are obvious: code is only loaded and parsed if it is really needed, without the necessesity to spread include_once all over the code base.

After dropping PHP 4 support, I suggest that we make use of this autoloading throughout the core, and establish an convention that can be used by plugins. Of course, it is possible that each plugin has its own autoloader (I've already done that for Feedview_XH 1.0beta1), but having a single autoloader would be more efficient, and also would favor a convention where to store classes in the file system.

We already have $pth['folder']['plugin_classes'] (pointing to plugins/*/classes/) and we have adopted the PEAR coding standards. Thus the autoloading strategy is rather obvious. Instead of a lenghty explanation regarding all the details, I give an implementation of what I'm thinking of:

Code: Select all

function XH_autoload($className)
{
    global $pth;

    // set $package, $subpackages and $class
    $subpackages = explode('_', $className);
    $packages = array_splice($subpackages, 0, 1);
    $package = $packages[0];
    $classes = array_splice($subpackages, -1);
    $class = $classes[0];

    // construct $filename
    if ($package == 'XH') {
        $folder = $pth['folder']['classes'];
    } else {
        $folder = $pth['folder']['plugins'] . strtolower($package) . '/classes/';
    }
    foreach ($subpackages as $subpackage) {
        $folder .= strtolower($subpackage) . '/';
    }
    $filename = $folder . $class . '.php';

    // possible error handling
    if (!file_exists($filename)) {
        // do something, or not
    }

    // include the class file
    include_once $filename;
} 
Of course, this would require to have only one class per file, but (a) this is customary nowadays (see PSR-0) and (b) the benefits of loading only actually required classes may compensate or even outweight the drawbacks.

A note for those prefering procedural code: of course, this will work as before, but it can't take advantage of autoloading. However, it is easily possible to convert all procedural code to a single class, converting each function to a static method and each global variable to a static property, and encapsulating remaing global scope code in one or more static methods. Furthermore you'd have to add simple wrapper functions for user callable functions (aka. "plugin calls"). This has at least the benefit of having a clean "namespace" for the plugin, without the need to prefix all global identifiers with the plugin name (inside of the class you can simply use self keyword to refer to the static members). Additionally, "large" plugin code bases could be split into multiple such classes, what seems to be a much cleaner solution than my "stub" suggestion.

Future scope: it might be reasonable to convert all "template tags" and especially "plugin calls" into static method calls. This would have the benefit of being able to cater for missing function definitions. Currently these will result in a fatal PHP error, but static method calls in combination with autoloading allow for ad-hoc definitions of fake classes (using __callStatic(); available since PHP 5.3.0) which will return a meaningful error message instead.

Thoughts?

Christoph
Christoph M. Becker – Plugins for CMSimple_XH

cmb
Posts: 14225
Joined: Tue Jun 21, 2011 11:04 am
Location: Bingen, RLP, DE
Contact:

Re: Autoloading of Classes

Post by cmb » Tue Feb 24, 2015 12:46 am

Done (r1490).
Christoph M. Becker – Plugins for CMSimple_XH

Post Reply