Working with PHP Namespacing

As a primarily WordPress developer, all the code I wrote for my plugins was following old standards WordPress used (and for the most part, it still does), and that is working without namespacing of the PHP code.

WordPress only recently dropped support for PHP 5.2, and PHP 5.2 had no support for namespacing. Because of that, WordPress code has all of its classes in the global PHP namespace and considering how large the WordPress codebase is, reorganizing the code will take quite some time.

For a while now, I planned to convert all my plugins, and better organize all the code to use namespacing, improving the plugin structure, take care of the optimized loading with the use of autoloader for the code, taking care of the possible conflicts, and making future development and debugging much easier. But, I have a lot of plugins on Dev4Press and making a change that big will take a lot of time, and it has to be done in stages.

Shared Code Library

All Dev4Press plugins use the same Dev4Press Library that includes a lot of base classes, functions, CSS and JS for the interface. Because of that library, all Dev4Press plugins share the same interface and don’t need to have so much code dedicated to the interface and other things.

And, this library is the best candidate to start the namespace conversion process. Once the conversion of the shared library is done, the work can be done on individual plugins.

So far, the progress on the shared library namespace conversion is about 50% done. The new version of the library will be available next week, and it will have a new structure of all library files, better organization of functions and a huge number of classes renamed and moved into namespace folder structure with the autoloader included.

The plan is to finish the conversion of the library by the end of the year.

The directory structure for the library namespace and the autoloader function.

Autoloader for the shared library

Here is the source for the autoload function used in the shared library.

function d4p_core_library_autoloader($class) {
    $path = dirname(__FILE__).'/';

    $parts = explode('\\', $class);

    $class_name = $parts[count($parts) - 1];
    unset($parts[count($parts) - 1]);

    $class_namespace = join('/', $parts);
    $class_namespace = strtolower($class_namespace);

    $path.= $class_namespace.'/'.$class_name.'.php';

    if (file_exists($path)) {
        include($path);
    }
}

spl_autoload_register('d4p_core_library_autoloader');

The function gets the full class name that also includes the namespace for the class. That means, that we can split every part of the namespace and use it as a directory. Because of that, the directory structure reflects the namespace structure (check the image above, it has the directory strucutre on the left).

So, if the namespace is DEV4PRESS\SERVICES\API, the autoload function will load requested class from a file in the path dev4press/services/api.

Advantage of Autoloader use

Autoloader doesn’t have to be used with namespace classes, it can load any class. But, using namespaces and the directory strucutre that mimics the namespace organization, makes the use of autoloader very logical step and makes the autoloader very simple. Also, PHP runs autoloaders only if the class is not found. That means that you don’t need to wrap classes in the class_exists() function check, and that is what I used in the shared library for all classes, because all plugins include the shared library, and all plugins load same files, so it is important to avoid loading class that already exists.

Autoloading solves all these issues, and with the use of namespaces, down the road, depending on changes, you can introduce versions for the same class by using additional namespace in the structure to indicate the version of the class.

I was avoiding the use of autoloader function in my code because I prefer using it with namespaced classes, and I postponed autoloader use until the code get’s properly namespaced.

Namespacing plugins

This is not going to happen quickly, but the goal is to start converting plugins to namespace structure from next month, and I hope I will be able to do it by the end of next year. When I get to work on the new major update for the plugin from next month, at least parts of the plugin will be namespaced.

Let me know if you use namespaces in WordPress related projects, and what experiences can you share if you converted your projects to namespaces.