Something that is slightly different in PHP than in most other programming languages is that importing or loading other classes can be done automatically and does not necessarily have to follow 1 set directory structure or naming convention to be able to find the actual files that belong to a class.
Instead every project or module can define their own logic to match class names to paths and consequently the files that hold the code of that class.
There are also (PSR) standards that can followed. These standards promote cooperation between frameworks and encourage people to unify the way they load their classes. At the time of writing this article, it is highly recommended to use PSR-4.
It is also possible to write PHP code without using an autoloader mechanism to find the files that belong to classes. Doing so requires us to use the include or require function in every class that needs to use another class, to specify where the file is located on the file system.
Conclusion: using an autoloading mechanism is much easier.
The autoloader is nothing more than a function that takes 1 argument (the class name) and is registered using the spl_autoload_register()
function.
The function should use the class name to generate a path on the file system that contains the actual code for that class. When the path is generated typically the require()
function is used to load the file and the code in the file is compiled into something that can be executed by the operating system. This compiling is done by the PHP interpreter (can be running inside apache as module, php.exe (on Windows), /usr/bin/php, etc...).
To be able to load classes using an autoloader mechanism the naming convention must match the logic in the autoloader function. Now if our application uses one convention and we want to use a module that uses a different convention, things can become quite complicated. Hence the need for a standard.
PSR-0 is a deprecated standard (in favor of PSR-4), but unfortunately there still is a lot of legacy code out there and the chances are big that you will eventually come across an application or module that follows this standard.
The standard basically states that namespace names should be used as directory names and that underscores '_' in class names should be replaced with directory separator characters.
For example:
More information can be found here: https://www.php-fig.org/psr/psr-0/.
PSR-4 no longer has any rules regarding to the underscore '_' characters in a class name. Instead it introduces a new concept: the namespace prefix.
Basically the namespace prefix is the first namespace and an optional number of sub namespaces. This is then stored somewhere together with a base path for that prefix, so we can know where to find the directory that contains the code of the deeper sub namespaces.
For example:
+------------------------------+-----------------+------------------------+-------------------------------------------+
| Class name | Prefix | Base path | File path |
+------------------------------+-----------------+------------------------+-------------------------------------------+
| \Acme\Log\Writer\File_Writer | Acme\Log\Writer | ./acme-log-writer/lib/ | ./acme-log-writer/lib/File_Writer.php |
| \Aura\Web\Response\Status | Aura\Web | /path/to/aura-web/src/ | /path/to/aura-web/src/Response/Status.php |
| \Symfony\Core\Request | Symfony\Core | ./vendor/Symfony/Core/ | ./vendor/Symfony/Core/Request.php |
| \Zend\Acl | Zend | /usr/includes/Zend/ | /usr/includes/Zend/Acl.php |
+------------------------------+-----------------+------------------------+-------------------------------------------+
More information can be found here: https://www.php-fig.org/psr/psr-4/.
As you might imagine having to generate a path, reading the file from the file system and finally compiling it, is a process that can be sped up significantly by not having to generate the paths over and over again for every class that is called.
A common way to speed up the process somewhat is to use a class map. Basically this is just an array in a PHP file of which the location is specified.
The key would be the class name and the value the path on the file system.
For example:
<?php
return [
'\Acme\Log\Writer\File_Writer' => './acme-log-writer/lib/File_Writer.php',
'\Aura\Web\Response\Status' => '\Aura\Web\Response\Status',
'\Symfony\Core\Request' => './vendor/Symfony/Core/Request.php',
'\Zend\Acl' => '/usr/includes/Zend/Acl.php',
];