Getting started with PHPVariablesArraysFunctional ProgrammingTypesAutoloading PrimerException Handling and Error ReportingWorking with Dates and TimeSending EmailSessionsCookiesClasses and ObjectsPassword Hashing FunctionsOutput BufferingJSONSOAP ClientReflectionUsing cURL in PHPDependency InjectionXMLRegular Expressions (regexp/PCRE)TraitsNamespacesParsing HTMLComposer Dependency ManagerMagic MethodsAlternative Syntax for Control StructuresFile handlingMagic ConstantsType hintingMulti Threading ExtensionFilters & Filter FunctionsGeneratorsOperatorsConstantsUTF-8URLsObject SerializationPHPDocContributing to the PHP ManualString ParsingLoopsControl StructuresSerializationClosureReading Request DataType juggling and Non-Strict Comparison IssuesSecurityPHP MySQLiCommand Line Interface (CLI)LocalizationDebuggingSuperglobal Variables PHPUnit TestingVariable ScopeReferencesCompilation of Errors and WarningsInstalling a PHP environment on WindowsDatetime ClassHeaders ManipulationPerformanceCommon ErrorsInstalling on Linux/Unix EnvironmentsContributing to the PHP CoreCoding ConventionsUsing MongoDBAsynchronous programmingUsing SQLSRVUnicode Support in PHPFunctionsCreate PDF files in PHPHow to Detect Client IP AddressYAML in PHPImage Processing with GDMultiprocessingSOAP ServerMachine learningCacheStreamsArray iterationCryptographyPDOSQLite3SocketsOutputting the Value of a VariableString formattingCompile PHP Extensionsmongo-phpManipulating an ArrayExecuting Upon an ArrayProcessing Multiple Arrays TogetherSPL data structuresCommentsIMAPUsing Redis with PHPImagickSimpleXMLHTTP AuthenticationRecipesBC Math (Binary Calculator)Docker deploymentWebSocketsAPCuDesign PatternsSecure Remeber Mephp mysqli affected rows returns 0 when it should return a positive integerPHP Built in serverHow to break down an URLPSR

Autoloading Primer

Other topics

Remarks:

Autoloading, as part of a framework strategy, eases the amount of boilerplate code you have to write.

Autoloading as part of a framework solution

// autoload.php
spl_autoload_register(function ($class) {
    require_once "$class.php";
});

// Animal.php
class Animal {
    public function eats($food) {
         echo "Yum, $food!";
    }
}

// Ruminant.php
class Ruminant extends Animal {
    public function eats($food) {
        if ('grass' === $food) {
            parent::eats($food);
        } else {
            echo "Yuck, $food!";
        }
    }
}

// Cow.php
class Cow extends Ruminant {
}

// pasture.php
require 'autoload.php';
$animal = new Cow;
$animal->eats('grass');

Thanks to our generic autoloader, we have access to any class that follows our autoloader naming convention. In this example, our convention is simple: the desired class must have a file in the same directory named for the class and ending in ".php". Notice that the class name exactly matches the file name.

Without autoloading, we would have to manually require base classes. If we built an entire zoo of animals, we'd have thousands of require statements that could more easily be replaced with a single autoloader.

In the final analysis, PHP autoloading is a mechanism to help you write less mechanical code so you can focus on solving business problems. All you have to do is define a strategy that maps class name to file name. You can roll your own autoloading strategy, as done here. Or, you can use any of the standard ones the PHP community has adopted: PSR-0 or PSR-4. Or, you can use composer to generically define and manage these dependencies.

Inline class definition, no loading required

// zoo.php
class Animal {
    public function eats($food) {
        echo "Yum, $food!";
    }
}

$animal = new Animal();
$animal->eats('meat');

PHP knows what Animal is before executing new Animal, because PHP reads source files top-to-bottom. But what if we wanted to create new Animals in many places, not just in the source file where it's defined? To do that, we need to load the class definition.

Manual class loading with require

// Animal.php
class Animal {
    public function eats($food) {
         echo "Yum, $food!";
    }
}

// zoo.php
require 'Animal.php';
$animal = new Animal;
$animal->eats('slop');

// aquarium.php
require 'Animal.php';
$animal = new Animal;
$animal->eats('shrimp');

Here we have three files. One file ("Animal.php") defines the class. This file has no side effects besides defining the class and neatly keeps all the knowledge about an "Animal" in one place. It's easily version controlled. It's easily reused.

Two files consume the "Animal.php" file by manually require-ing the file. Again, PHP reads source files top-to-bottom, so the require goes and finds the "Animal.php" file and makes the Animal class definition available before calling new Animal.

Now imagine we had dozens or hundreds of cases where we wanted to perform new Animal. That would require (pun-intended) many, many require statements that are very tedious to code.

Autoloading replaces manual class definition loading

// autoload.php
spl_autoload_register(function ($class) {
    require_once "$class.php";
});

// Animal.php
class Animal {
    public function eats($food) {
         echo "Yum, $food!";
    }
}

// zoo.php
require 'autoload.php';
$animal = new Animal;
$animal->eats('slop');

// aquarium.php
require 'autoload.php';
$animal = new Animal;
$animal->eats('shrimp');

Compare this to the other examples. Notice how require "Animal.php" was replaced with require "autoload.php". We're still including an external file at run-time, but rather than including a specific class definition we're including logic that can include any class. It's a level of indirection that eases our development. Instead of writing one require for every class we need, we write one require for all classes. We can replace N require with 1 require.

The magic happens with spl_autoload_register. This PHP function takes a closure and adds the closure to a queue of closures. When PHP encounters a class for which it has no definition, PHP hands the class name to each closure in the queue. If the class exists after calling a closure, PHP returns to its previous business. If the class fails to exist after trying the entire queue, PHP crashes with "Class 'Whatever' not found."

Autoloading with Composer

Composer generates a vendor/autoload.php file.

You might simply include this file and you will get autoloading for free.

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

This makes working with third-party dependencies very easy.


You can also add your own code to the Autoloader by adding an autoload section to your composer.json.

{
    "autoload": {
        "psr-4": {"YourApplicationNamespace\\": "src/"}
    }
}

In this section you define the autoload mappings. In this example its a PSR-4 mapping of a namespace to a directory: the /src directory resides in your projects root folder, on the same level as the /vendor directory is. An example filename would be src/Foo.php containing an YourApplicationNamespace\Foo class.

Important: After adding new entries to the autoload section, you have to re-run the command dump-autoload to re-generate and update the vendor/autoload.php file with the new information.

In addition to PSR-4 autoloading, Composer also supports PSR-0, classmap and files autoloading. See the autoload reference for more information.


When you including the /vendor/autoload.php file it will return an instance of the Composer Autoloader. You might store the return value of the include call in a variable and add more namespaces. This can be useful for autoloading classes in a test suite, for example.

$loader = require __DIR__ . '/vendor/autoload.php';
$loader->add('Application\\Test\\', __DIR__);

Syntax:

  • require
  • spl_autoload_require

Contributors

Topic Id: 388

Example Ids: 1287,1284,1285,1286,1528

This site is not affiliated with any of the contributors.