When you are developing a medium-large application chances are, and a good practice as well, you want to split your codebase up in different files. Although this may seem a trivial task, it involves many steps and details that may escape at a first look.

After splitting the files up, one question that many developers have is: How do I load all those files so i can later use them? There is no single (nor simple) answer to that question, however it can be summed up in two processes: manual loading and autoloading. I will try to briefly explore these two options while integrating them in a WordPress basic application.

Manual loading

One way to have your files and classes available to use, is to “require” them. In a WordPress installation you most likely will do that within the functions.php .

For example:

<?php 
require_once('foo.php'); 
require_once('bar.php'); 
require_once('baz.php'); 
//...

As you can see I required three files. This method has a clear downside, those files will always be loaded no matter what. That means the scripts in those files will be loaded even if I don’t use their functionality. This translates to using up/wasting precious memory.

Another way of manually requiring a file is the following:

<?php
// File Foo.php

class Foo {
    private static $instance;

    public static function get_instance() {
        if ( ! isset( self::$instance ) ) {
            self::$instance = new Foo;
            self::$instance->require_files();
        }

        return self::$instance;
    }

    private function require_files() {
        //Files to require
        require_once dirname( __FILE__ ) . '/lib/bar.php';
        require_once dirname( __FILE__ ) . '/lib/baz.php';
    }
}

Foo::get_instance();

As you can see, in the file Foo.php I have required bar.php and baz.php within the require_files() method. That mean that every time I instantiate an object of the Foo class, the two files are loaded. This is a good improvement on the first method, but I still need to load the files even if I may not need their content.

Surely I could add some conditions to the files loading, but there must be a better way. And there is!

Autoloading

What if I could load a file only when instantiating an object of its contained class? That is exactly what the following autoloader does.

<?php

/**
 * Registering PSR-4 compliant namespaces
 *
 * @see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md
 *
 * @param string $class The fully-qualified class name.
 *
 * @return void
 */
spl_autoload_register( function ( $class ) {

    // project-specific namespace prefix
    $prefix = 'Project\\Lib\\';

    // base directory for the namespace prefix
    $base_dir = __DIR__ . '/lib/';

    // does the class use the namespace prefix?
    $len = strlen( $prefix );
    if ( strncmp( $prefix, $class, $len ) !== 0 ) {
        // no, move to the next registered autoloader
        return;
    }

    // get the relative class name
    $relative_class = substr( $class, $len );

    // replace the namespace prefix with the base directory, replace namespace
    // separators with directory separators in the relative class name, append
    // with .php
    $file = $base_dir . str_replace( '\\', '/', $relative_class ) . '.php';

    // if the file exists, require it
    if ( file_exists( $file ) ) {
        require $file;
    }
} );

In the previous example, I register our autoloading function with the spl_autoload_register().  This will add the code to an autoload queue, and will run it in the order it was registered. It also enables multiple autoload functions to be registered, should you need to.

In this specific case, I also follow the PSR4 namespacing, which allows a clean and simple structure for any project. The function will check if the requested class is registered within the predefined namespace and, if so, will require the relative file.

Once registered, you can call $foo = new Foo(); and the autoloader will require the Foo.php for you.

That is a huge time, and memory saver. Your application will run smoother and your code-base will be more organized. 

References:

http://php.net/manual/en/function.spl-autoload-register.php

http://www.php-fig.org/psr/psr-4/

http://www.php.net/autoload

http://php.net/manual/en/language.namespaces.php