Autoloading in Zend Framework 2

A web application consists of many PHP classes, and each class typically resides in a separate file. This introduces the need of including the files.

For example, let’s assume we have the file named Application.php which contains the definition for the \Zend\Mvc\Application class. Before you can create an instance of the Application class somewhere in your code, you have to include the contents of Application.php file (you can do this with the help of require_once statement, passing it the full path to the file):

<?php
require_once "/path/to/zend/lib/Application.php";

use Zend\Mvc\Application;

$application = new Application;

As your application grows in size, it may be difficult to include each needed file. Zend Framework 2 itself consists of hundreds of files, and it can be very difficult to load the entire library and all its dependencies this way. Moreover, when executing the resulting code, PHP interpreter will take CPU time to process each included file, even if you don’t create an instance of its class.

To fix this problem, in PHP 5.1, the class autoloading feature has been ntroduced.
The PHP function spl_autoload_register() allows you to register an autoloader function. For complex web sites, you even can create several autoloader functions, which are chained in a stack.

During script execution, if PHP interpreter encounters a class name which has not been defined yet, it calls all the registered autoloader functions in turn, until either the autoloader function includes the class or “not found” error is raised. This allows for “lazy” loading, when PHP interpreter processes the class definition only at the moment of class invocation, when it is really needed.

To give you an idea of how an autoloader function looks like, below we provide a
simplified implementation of an autoloader function:

<?php
// Autoloader function.
function autoloadFunc($className) {
  
  // Class map static array.
  static $classMap = array(
    'Zend\\Mvc\\Application' => '/path/to/zend/dir/Zend/Mvc/Application.php',
    'Application\\Module' => '/path/to/app/dir/Application/Module.php',
    //...
  );

  // Check if such a class name presents in the class map.
  if(isset(static::$classMap[$className])) {
    $fileName = static::$classMap[$className];
  
    // Check if file exists and is readable.
    if (is_readable($filename)) {
      // Include the file.
      require $filename;
    }
  }
}

// Register our autoloader function.
spl_autoload_register("autoloadFunc");

In the above example, we define the autoloadFunc() autoloader function, which we will further refer to as the class map autoloader.

The class map autoloader uses the class map for mapping between class name and absolute path to PHP file containing that class. The class map is just a usual PHP
array containing keys and values. To determine the file path by class name, the class map autoloader just needs to fetch the value from the class map array. It is obvious, that the class map autoloader works very fast. However, the disadvantage of it is that you have to maintain the class map and update it each time you add a new class to your program.

PSR-0 Standard

Because each library’s vendor uses its own code naming and file organization conventions, you will have to register a different custom autoloader function per each dependent library, which is rather annoying (and actually this is an unneeded work). To resolve this problem, the PSR-0 standard was introduced.

The PSR-0 standard (PSR stands for PHP Standards Recommendation) defines the recommended code structure that an application or library must follow to guarantee autoloader interoperability. In two words, the standard says that:

  • The class namespaces should be organized in the following way:
\<Vendor Name>\(<Namespace>)*\<Class Name>
  • Namespaces can have as many nesting levels as desired, but the Vendor Name should be the top-level namespace.

  • Namespaces should map to directory structure. Each namespace separator (‘\’) is converted to a OS-specific DIRECTORY_SEPARATOR constant when loading from the file system.

  • The class name is suffixed with .php extension when loading the file from the file system.

For example, for the Zend\Mvc\Application class, you will have the following directory structure:

/path/to/zend/lib
  /Zend
    /Mvc
       Application.php

For the code conforming to the PSR-0 standard, we can write and register an autoloader, which we will refer to as the “standard” autoloader:

<?php

// "Standard" autoloader function.
function standardAutoloadFunc($className) {
	
  // Replace special characters in class name.
  $className = str_replace('\\', '/', $className);
  // Format the file path.
  $fileName = "path/to/zend/dir/" . $className . ".php";
  // Check if file exists and is readable.
  if (is_readable($fileName)) {
    // Include the file.
    require $fileName;
  } 
}

// Register the autoloader function.
spl_autoload_register("standardAutoloadFunc");

The standard autoloader works as follows. Assuming that the class namespace can be mapped to the directory structure one-by-one, the function calculates the path to PHP file by transforming back-slashes (namespace separators) to forward slashes (path separators) and concatenating the resulting path with the absolute path to the directory where the library is located. Then the function checks if such a PHP file really exists, and if so, includes it with the require statement.

It is obvious, that the standard autoloader works slower than the class map autoloader. However, its advantage is that you don’t need to maintain any class map, which is very convenient when you develop new code and add new classes to your application.

Zend Framework 2 conforms to PSR-0 standard, making it possible to use standard autoloading mechanism across all its components. It is also compatible with other PSR-0 conforming libraries like Doctrine or Symfony 2.

Note: This post is an excerpt from my Using Zend Framework 2 e-book.

Advertisements

I am a software developer currently living in Tomsk, Russia. I received a PhD degree in Computer Science from Tomsk Polytechnic University in 2010. I have been professionally developing C/C++ and PHP software since 2005. I like contributing to open-source and writing programming articles for popular web resources, like CodeProject. Besides writing, I love skiing and watching Formula-1.

Tagged with: ,
Posted in Zend Framework 2

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow ValuableThing on WordPress.com
%d bloggers like this: