Autoloading classes in an any PHP project with Symfony2 ClassLoader component
Symfony ClassLoader component is a PSR-0 standard compliant PHP class autoloader. It's not only able to load namespaced code but also supports old-school PEAR standards (also used by Zend Framework). It's a perfect class loading tool for most of PHP projects.
Note: Code used in this post is available on github: https://github.com/jakzal/SymfonyComponentsExamples
Installation
You can either install it from the Symfony PEAR channel or grab it directly from github. For the purpose of this article we'll clone the sources to the vendor/ directory of the project.
Note: ClassLoader component uses Symfony\Component\ClassLoader namespace. Therefore we'll put it into Symfony/Component/ClassLoader subdirectory of vendor (see PSR-0 standard).
git clone https://github.com/symfony/ClassLoader.git vendor/Symfony/Component/ClassLoader
Basic Usage
Let's say we have two Acme libraries.
First one is located in the src/Acme/Tools. HelloWorld class uses Acme\Tools namespace and is declared in the src/Acme/Tools/HelloWorld.php file:
<?php
// src/Acme/Tools/HelloWorld.php
namespace Acme\Tools;
class HelloWorld
{
public function __construct()
{
echo __METHOD__."\n";
}
}Second library is stored in the src/Legacy/Acme/Tools. It follows old but well known PEAR naming standards. Legacy_Acme_Tools_HelloWorld class is defined in the src/Legacy/Acme/Tools/HelloWorld.php file:
<?php
// src/Legacy/Acme/Tools/HelloWorld.php
class Legacy_Acme_Tools_HelloWorld
{
public function __construct()
{
echo __METHOD__."\n";
}
}To make that our classes are automatically loaded we have to register Acme namespace and Legacy_ prefix:
<?php
// classloader.php
require_once __DIR__.'/vendor/Symfony/Component/ClassLoader/UniversalClassLoader.php';
$loader = new Symfony\Component\ClassLoader\UniversalClassLoader();
$loader->registerNamespaces(array('Acme' => __DIR__ . '/src'));
$loader->registerPrefixes(array('Legacy_' => __DIR__ . '/src'));
$loader->register();
$helloWorld = new Acme\Tools\HelloWorld();
$legacyHelloWorld = new Legacy_Acme_Tools_HelloWorld();Of course classes are only loaded when needed. Requiring UniversalClassLoader.php file should be the only require statement used in our code. Other classes should be loaded by the class loader.
Note: There's also a way to define paths with registerNamespaceFallbacks() and registerPrefixFallbacks(). Class loader will use them with namespaces or prefixes which weren't listed explicitly.
Increasing performance
Number of class files in a real-world project is rather big. Class loader might have some impact on performance as it checks for file existence before requiring it. To avoid disk operations we can cache results in APC with ApcUniversalClassLoader:
<?php
// classloadercached.php
require_once __DIR__.'/vendor/Symfony/Component/ClassLoader/UniversalClassLoader.php';
require_once __DIR__.'/vendor/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php';
$loader = new Symfony\Component\ClassLoader\ApcUniversalClassLoader('ClassLoader');
$loader->registerNamespaces(array('Acme' => __DIR__ . '/src'));
$loader->registerPrefixes(array('Legacy_' => __DIR__ . '/src'));
$loader->register();
$helloWorld = new Acme\Tools\HelloWorld();
$legacyHelloWorld = new Legacy_Acme_Tools_HelloWorld();Note: Examples are run in a command line. Therefore there's no performance gain from using APC. In fact it can hurt performance as cache is initialized every time our script is run in cli. This is a limitation of APC.
Comments
about 1 year ago wrote:I see that in the repository you have included the ClassLoader as a submodule. It would be helpful to list the commands used here instead of the clone. :)
about 1 year ago wrote:@Giorgio thanks for suggestion! I'm trying to describe all components and I'm still looking for best way to do that.
about 1 year ago wrote:actually many methods in classloader
but I see it is very simple and goes well
about 1 year ago wrote:Argh, I wish I had found this tutorial when I was trying to set up my project to use the console component.
I created a similar tutorial myself that shows how to do this with Composer - http://talater.com/symfony_console_component/- Write a comment



















