Autoloading in Drupal 8

Autoloading in Drupal 8 image

We are introduced to the concept of autoloading near the top of the index.php file of Drupal 8:

$autoloader = require_once 'autoload.php';

What is autoloading?

Autoloading is a unified way of including files anywhere in an application while ensuring they are found at a specified location. It boils down to a method or function that generates require statements for as many files as determined by the code.

In the early days of PHP applications, as scripts grew in size, it became common practice to include a file in others either for file size management or code reuse. Understandably, there is no limit to the number of includes and they can come anywhere in a file but often at the very top.

PHP applications grew in complexity, and each version introduced new features. The ones that drew the most attention were in Object-Oriented Programming (OOP), which modern programming languages touted. The basic premise was seeing the abstract world of bytes in the light of a physical world of objects with properties and behaviors. Coding in this way added classes to the existing concepts of variables, statements, functions (or methods). A simple application may have hundreds of files or classes. Autoloading is an effective way of managing them.

So getting an instance of the autoloader stored in $autoloader very early in the application life-cycle is perfect. The PHP parser looks for the autoload.php file in the same directory as index.php and includes it.

Let us see the magic inside the included file:

// autoload.php
return require __DIR__ . '/vendor/autoload.php';

Another require statement? Another autoload.php? The difference here is that the statement is require unlike require_once in index.php. And more importantly, something is returned and whatever is returned is stored in the $autoloader variable we saw earlier in index.php.

This second autoload file is important because the vendor folder might be in a different location. The file is quite similar to the first one.

require_once __DIR__ . '/composer' . '/autoload_real.php';

return ComposerAutoloaderInitDrupal8::getLoader();

Initially, this might look confusing, but we shall see the reasoning behind this in a second. With this final require statement we end up with a ComposerAutoloaderInitDrupal8 class, which is defined in vendor/composer/autoload_real.php, and call its getLoader() method.

When Composer has downloaded the dependencies for a site, it generates some autoload classes with arrays of namespaces and class maps under vendor/composer. Inside the same folder as autoload_real.php we also have autoload_classmap.php, autoload_files.php, autoload_namespaces.php, autoload_psr4.php, and autoload_static.php. These are different ways of identifying the location of classes available in the packages under the vendor folder.

In the getLoader() method, depending on whether a static loader is to be used or not, the right autoload classes are included, and the \Composer\Autoload\ClassLoader instance is properly initialized.

The returned object is passed on to the second require statement, which in turn gets passed on to the line in our index.php file and assigned to a variable - $autoloader.

Fine-tuning Class Loading

Adding some entries to settings.php file allows you to have a finer level of control over the class-loading process. If the APC extension for PHP is available on the server, the Symfony APC class loader is used for improved performance. If you do not want this detection, make sure this is in your settings.php. It should already be there in a commented line - just uncomment it:

$settings['class_loader_auto_detect'] = FALSE;

Even without the APC extension, you can still benefit from Symfony's APC class loader by decorating and replacing the local $class_loader variable. Uncomment the following lines in settings.php and see the comment above the code block for further details about it:

if ($settings['hash_salt']) {
  $prefix = 'drupal.' . hash('sha256', 'drupal.' . $settings['hash_salt']);
  $apc_loader = new \Symfony\Component\ClassLoader\ApcClassLoader($prefix, $class_loader);
  unset($prefix);
  $class_loader->unregister();
  $apc_loader->register();
  $class_loader = $apc_loader;
}

Conclusion

Modern PHP web applications may pull a large number of packages and libraries from different sources. They manage package dependencies with Composer which provides a central way of finding classes and making them available throughout an application. Drupal 8 is an excellent exponent of autoloading which plays a key role in the journey of an HTTP request from the moment it arrives at the front controller, the index.php file.

KEEP MOVING FORWARD

Deji Akala / code