Navigation

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.

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:

<?phpnamespaceMyProject\Shipping;classShippingStrategy{...}

resides in the following directory structure:

src/
/MyProject
/Shipping
ShippingStrategy.php

Note that the name of “src” or the structure above or beside this
directory is completely arbitrary. “src” could be named “classes”
or “lib” or whatever. The only convention to adhere to is to map
namespaces to directories and classes to files named after the
class name.

To use a Doctrine Common ClassLoader, you first need to load the
class file containing the ClassLoader. This is the only class file
that actually needs to be loaded explicitly via require. All
other classes will be loaded on demand by the configured class
loaders.

A ClassLoader takes two constructor parameters, both optional.
In the normal case both arguments are supplied. The first argument
specifies the namespace prefix this class loader should be
responsible for and the second parameter is the path to the root
directory where the classes can be found according to the
convention mentioned previously.

The class loader in the example above would thus be responsible for
all classes under the ‘MyProject’ namespace and it would look for
the class files starting at the directory ‘/path/to/src’.

Also note that the prefix supplied in the first argument need not
be a root namespace but can be an arbitrarily nested namespace as
well. This allows you to even have the sources of subnamespaces
split across different directories. For example, all projects under
the Doctrine umbrella reside in the Doctrine namespace, yet the
sources for each project usually do not reside under a common root
directory. The following is an example of configuring three class
loaders, one for each used Doctrine project:

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.

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!):

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:

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):

<?php// Equivalent to if (class_exists('Foo', true)) if there is only 1 class loader to checkif(class_exists('Foo',false)||$classLoader->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):

This static method can basically be used as a drop-in replacement
for class_exists(..., true). It iterates over all installed class
loaders and asks each of them via canLoadClass, returning early
(with TRUE) as soon as one class loader returns TRUE from
canLoadClass. If this sounds like it can potentially be rather
costly then because that is true but it is exactly the same thing
that class_exists(..., true) does under the hood, it triggers a
complete interaction of all class/auto loaders. Checking for class
existence via invoking autoloading was never a cheap thing to do
but now it is more obvious and more importantly, this check is no
longer interleaved with regular class loading, which avoids having
to check each and every class for existence prior to loading it.
The vast majority of classes to be loaded are not optional and a
failure to load such a class is, and should be, a fatal error. The
ClassLoader design reflects this.

If you have code that requires the usage of class_exists(...,
true) or ClassLoader::classExists during normal runtime of the
application (i.e. on each request) try to refactor your design to
avoid it.

No matter which class loader you prefer to use (Doctrine classes do
not care about how they are loaded), we kindly encourage you to
adhere to the simple convention of mapping namespaces and class
names to a directory structure.

Class loading should be simple, automated and uniform. Time is
better invested in actual application development than in designing
special directory structures, autoloaders and clever caching
strategies for class loading.