All about OPL autoloader
From Invenzzia wiki
Open Power Libs projects do not manage their class loading manually. Instead, they use an autoloading utility that is included in OPL core. This short article explains all its features and shows, how to use it properly.
Contents |
General overview
If PHP cannot find a class that we want to create an object of, it may call special functions or methods named "autoloaders". Their task is to find the file with the class source code and load it, so that the object could be created. Entire process is fully transparent for the programmer and provides a better code flexibility. In the new versions of PHP, there can be many autoloaders registered - they are processed in a chain. If one autoloader notices that it cannot find the class or cannot recognize the class name as "its", PHP asks the next autoloader in the list and so on.
Open Power Libs provide their own autoloader, which is oriented to handle the Library_Class_Name class naming format which is mapped to Library/Class/Name.php file. It can be used with many other libraries, for example Zend Framework and Doctrine, because they follow this convention, similarly to OPL. The advantage over registering different autoloaders is convenience and performance. The OPL autoloader is highly configurable and it understands the concept of "libraries". The first part of the class name is used to detect, which library it belongs to and load its specific rules. Furthermore, it does not use include_path at all, which may be very slow with the bigger amount of libraries used in the project or improperly constructed path list.
Basic usage
Although the autoloader allows to load the classes automatically, its code itself has to be included by the programmer manually. The autoloading code is stored in the Opl_Loader class in Opl/Base.php file (it is a part of the OPL core). To start using it, you must add the following lines somewhere to your code:
<?php
require('./path/to/Opl/Base.php');
Opl_Loader::setDirectory('./path/to/');
Opl_Loader::register();
In this scenario we assume that all the libraries are stored under ./path/to/ directory, for example ./path/to/Opl/ or ./path/to/Opt/. The setDirectory() static method allows us to specify this path. Then, we register the autoloader in PHP with Opl_Loader::register().
Library handlers
Some libraries may use some extensions to the basic class-filesystem mapping rule. For example, Open Power Libs use the following extra rules:
- The
Opx/Class.phpfile is considered to be the main library file. It must be loaded before any other file from this library and it may contain more than one class or interface. - All the exceptions are stored in
Opx/Exception.phpand have the name in the formatOpx_Something_Exception - If OPL runs on PHP 5.2, it must load the PHP compatibility layer which emulates some classes that appear in PHP 5.3.
Such special behaviours are supported by autoloading handlers which are executed before the default rule is applied. They can be registered at the autoloader or library level. In the first case, the handler is applied for all the libraries, and in the second - only to the one of them. By default, the autoloader registers the standard OPL handler and to work with non-OPL libraries, you will probably want to turn it off.
// Registers different default handler
Opl_Loader::setDefaultHandler(array('myClass', 'myHandler'));
// Disables the handlers at the autoloader level - they must be configured manually for each library.
Opl_Loader::setDefaultHandler(null);
Library configuration
To configure a single library, we use the Opl_Loader::addLibrary() method. Below, you can find a sample use:
Opl_Loader::addLibrary('Opl', array(
'directory' => './path/to/Opl/',
'handler' => array('Opl_Loader', 'oplHandler')
));
As we can see, our libraries do not necessarily have to lie in the same repository, as we can point them to a very different place. Furthermore, we can set the library-specific autoloading handler. If the handler element is not provided, the autoloader uses the default handler. If it is set to null, the library does not use any handler.
Another possible element is basePath. Its behaviour is very similar to directory. We show it on the example of Doctrine ORM, which has the following directory structure:
lib/Doctrine/ lib/Doctrine/(lots of classes here) lib/Doctrine.php
The lib/Doctrine.php contains the Doctrine class, which must be also handled by the autoloader. Basically, we can register Doctrine in OPL in two ways:
// option 1
Opl_Loader::addLibrary('Doctrine', array('directory' => './lib/Doctrine/', 'handler' => null));
// option 2
Opl_Loader::addLibrary('Doctrine', array('basePath' => './lib/', 'handler' => null));
So, you can think of it like of a sort of syntactic sugar. In the second option, the autoloader simply appends the library name to the path. To get to know more about integrating OPL and Doctrine, see Using OPC and OPL with Doctrine ORM.
You do not have to call
Opl_Loader::setDirectory()method, if you do not make a real use it.
What about unregistered libraries?
By default, if the library was not registered with Opl_Loader::addLibrary(), the autoloader attempts to apply the default rules for it. In some cases, we may not want to touch the libraries that are not registered explicitely. We can inform the autoloader about it with the following code:
Opl_Loader::setHandleUnknownLibraries(false);
Manual class mapping
Another feature of the OPL autoloader is the ability to register an explicite path to a class file.
Opl_Loader::map('Library_Some_Class', 'Sth/Else/Somefile.php');
Opl_Loader::mapAbsolute('Library_Another_Class', '../app/theClass.php');
With map() method, we specify the alternative path within the library directory, whereas mapAbsolute() allows us to define the absolute path, not related to the library path.
Namespace support
Currently, the autoloader is not able to handle PHP namespaces that appeared in PHP 5.3. However, this feature is planned for the future releases.
Compatibility guide
The autoloader has already been tested with:
- OPL - works without any problems
- Zend Framework - successfully replaces the standard autoloader (tested with versions 1.7, 1.8 and 1.9)
- Doctrine ORM - see Using OPC and OPL with Doctrine ORM
Conclusion
As you see, OPL autoloader is a very flexible tool. Obviously you will not be using many of its features most of the time, however - they are sometimes used transparently by the libraries themselves. In case of any problems it is good to know, how it works and where to look for a solution.

