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;
}
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