Class Loading ============= Class loading is an essential part of any PHP application that makes heavy use of classes and interfaces. Unfortunately, a lot of people and projects spend a lot of time and effort on custom and specialized class loading strategies. It can quickly become a pain to understand what is going on when using multiple libraries and/or frameworks, each with its own way to do class loading. Class loading should be simple and it is an ideal candidate for convention over configuration. Overview -------- The Doctrine Common ClassLoader implements a simple and efficient approach to class loading that is easy to understand and use. The implementation is based on the widely used and accepted convention of mapping namespace and class names to a directory structure. This approach is used for example by Symfony2, the Zend Framework and of course, Doctrine. For example, the following class: .. code-block:: php register(); $dbalLoader->register(); $ormLoader->register(); Do not be afraid of using multiple class loaders. Due to the efficient class loading design you will not incur much overhead from using many class loaders. Take a look at the implementation of ``ClassLoader#loadClass`` to see how simple and efficient the class loading is. The iteration over the installed class loaders happens in C (with the exception of using ``ClassLoader::classExists``). A ClassLoader can be used in the following other variations, however, these are rarely used/needed: - If only the second argument is not supplied, the class loader will be responsible for the namespace prefix given in the first argument and it will rely on the PHP include_path. - If only the first argument is not supplied, the class loader will be responsible for *all* classes and it will try to look up *all* classes starting at the directory given as the second argument. - If both arguments are not supplied, the class loader will be responsible for *all* classes and it will rely on the PHP include_path. File Extension -------------- By default, a ClassLoader uses the ``.php`` file extension for all class files. You can change this behavior, for example to use a ClassLoader to load classes from a library that uses the ".class.php" convention (but it must nevertheless adhere to the directory structure convention!): .. code-block:: php setFileExtension('.class.php'); $customLoader->register(); Namespace Separator ------------------- By default, a ClassLoader uses the ``\`` namespace separator. You can change this behavior, for example to use a ClassLoader to load legacy Zend Framework classes that still use the underscore "_" separator: .. code-block:: php setNamespaceSeparator('_'); $zend1Loader->register(); Failing Silently and class_exists ---------------------------------- A lot of class/autoloaders these days try to fail silently when a class file is not found. For the most part this is necessary in order to support using ``class_exists('ClassName', true)`` which is supposed to return a boolean value but triggers autoloading. This is a bad thing as it basically forces class loaders to fail silently, which in turn requires costly file_exists or fopen calls for each class being loaded, even though in at least 99% of the cases this is not necessary (compare the number of class_exists(..., true) invocations to the total number of classes being loaded in a request). The Doctrine Common ClassLoader does not fail silently, by design. It therefore does not need any costly checks for file existence. A ClassLoader is always responsible for all classes with a certain namespace prefix and if a class is requested to be loaded and can not be found this is considered to be a fatal error. This also means that using class_exists(..., true) to check for class existence when using a Doctrine Common ClassLoader is not possible but this is not a bad thing. What class\_exists(..., true) actually means is two things: 1) Check whether the class is already defined/exists (i.e. class_exists(..., false)) and if not 2) check whether a class file can be loaded for that class. In the Doctrine Common ClassLoader the two responsibilities of loading a class and checking for its existence are separated, which can be observed by the existence of the two methods ``loadClass`` and ``canLoadClass``. Thereby ``loadClass`` does not invoke ``canLoadClass`` internally, by design. However, you are free to use it yourself to check whether a class can be loaded and the following code snippet is thus equivalent to class\_exists(..., true): .. code-block:: php canLoadClass('Foo')) { // ... } The only problem with this is that it is inconvenient as you need to have a reference to the class loaders around (and there are often multiple class loaders in use). Therefore, a simpler alternative exists for the cases in which you really want to ask all installed class loaders whether they can load the class: ``ClassLoader::classExists($className)``: .. code-block:: php