PHP Composer … The Autoloader

PHP Composer … The AutoloaderMustafa MagdiBlockedUnblockFollowFollowingFeb 20, 2018https://commons.

wikimedia.

org/wiki/File:Logo-composer-transparent.

pngComposer is the most awesome tool for any PHP developer that made managing dependencies for any application packages hassle-free.

In the following sections, I am not going to talk about the main function of composer -which is managing dependencies- and I am going to focus on how applications do manage loading a big number of packages by composer.

What is Autoloading.

Let us Create our Autoloader.

How Composer Does Autoloading.

Classmap vs.

PSR-0 vs.

PSR-4.

Conclusion.

References.

1.

What is AutoloadingOne of the biggest annoyances is having to write a long list of needed includes at the beginning of each script.

Problem: Supposing that you are developing an application and you have a long list of libraries that needed to be loaded.

Solution: Load all of classes at the beginning of your script and you will be able to use any one of these classes anywhere in your application.

Better Solution: Whenever I use a class, I go and load it, so my application doesn’t have to load all classes each request, this is called “Autoloading”.

But how to achieve that?… let us figure out:2.

Let us Create our AutoloaderThe simplest solution, we include all the files:<?php// Classes/A.

phpclass A {}<?php// Classes/B.

phpclass B {}<?php// index.

phpinclude_once 'Classes/A.

php';include_once 'Classes/B.

php';// load A class$a = new A();// check the list of all loaded filesvar_dump(get_included_files());The script index.

php will output:array(3) { [0]=> string(20) "/path/to/root/index.

php" [1]=> string(24) "/path/to/root/Classes/A.

php" [2]=> string(24) "/path/to/root/Classes/B.

php"}Which means that we loaded all the files whether we used class B or not, and as long as your project is going bigger and bigger, this way is not going to work.

Here comes the Autoloading to solve the problem:<?php// index.

php// my custom autoloaderfunction my_autoloader($class) { include 'Classes/' .

$class .

'.

php';}// register the autoloaderspl_autoload_register('my_autoloader');// load A class$a = new A();// check the list of all loaded filesvar_dump(get_included_files());You write the way you do “mapping” between class name and its file path in my_autoloader() function and register it in your script so you tell your script that any time you instantiate a class, just go and look for it through this function and load it.

Now, check the number of files loaded in your script:array(2) { [0]=> string(50) "/path/to/demos/autoload-2/index.

php" [1]=> string(54) "/path/to/demos/autoload-2/Classes/A.

php"}Now, your script loads the files that it just needs.

PHP is telling you “I will give you the chance to go and load your class even if you didn’t load it before your statement $a = new A(); after that, I will throw an error if it didn’t work”.

The preceding example works alright, but you have to consider the following:File name should have the same class name.

Every single file should have only one class.

Sensitivity in classes names and files names.

You can handle all these situations with your own implementation, and any application can do its own mapping based on its file structure, but in order to use this autoloader, you have to follow the preceding considerations.

Composer comes up with a way that suits most of structures (or you can say that it forces the applications to choose between), let us dig a bit deeper in it.

3.

How Composer Does AutoloadingAlong with your script index.

php add your composer.

json:{ "autoload": { "classmap": [ "Classes/" ] }}And update your index.

php file to:require __DIR__ .

'/vendor/autoload.

php';$a = new A();Using classmap, we are telling composer that this is the way to do mapping, and it is a very basic way to map namespaces to paths and if you want more details, just check vendor/composer/autoload_classmap.

php after you run the composer install:return array( 'A' => $baseDir .

'/Classes/A.

php', 'B' => $baseDir .

'/Classes/B.

php',);And whenever you instantiate A class, it is loading the $baseDir .

'/Classes/A.

php' file.

The flow is easy to understand.

It is always starts from following line in you front controller:require __DIR__.

'/.

/vendor/autoload.

php';And you will realize that ComposerAutoloaderInitXXXX:getLoader() has all the logic, which is adding different mappings and at the end of it, it is registering the autoloader:// ComposerComposerAutoloaderInitXXXX:getLoader()public static function getLoader() { .

$loader->register(true); // ComposerClassLoader::register() return $loader;}And here is where we register our autoloader:// ComposerClassLoader::register()public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend);}And whenever we instantiate a class it goes to ClassLoader::loadClass() to find the corresponding file and load it.

4.

Classmap vs.

PSR-0 vs.

 PSR-4All of them are different ways to map the namespaces with their corresponding paths, once you choose one of them, you have to follow their rules and at the end, composer knows how to find and load the file based on the mapping you’re following.

a) Classmap: is the simplest and most straightforward, it prints the logic in the vendor/composer/autoload_classmap.

php, when composer reads that we are using autoload classmap, it is scanning all the files in the mentioned directories (in composer.

json file) and create an array of namespaces and the corresponding paths.

Note: adding new files requires composer dumpautoload to regenerate the mapping.

b) PSR-0: the logic exists in vendor/composer/autoload_namespaces.

php, and -from its name- it follows the rules of PSR-0.

c) PSR-4: the logic exists in vendor/composer/autoload_psr4.

php, and -from its name- it follows the rules of PSR-4.

Both of PSR-0 and PSR-4 are almost have the same rules.

Note the following:For both, you don’t have to run composer dumpautoload every time you add a new PHP class because “searching for file path” process is going dynamically.

You have to use namespaces, especially with PSR-4 because the namespace is attached to the file path.

The subdirectory name MUST match the case of the sub-namespace names.

-PSR-4PSR-0 converts the underscores to directory separator, and it doesn’t in PSR-4:Each _ character in the CLASS NAME is converted to aDIRECTORY_SEPARATOR.

The _ character has no special meaning in thenamespace.

-PSR-0So $a = new Classes_A(); will load the following file:<?php// path /Classes/A.

phpclass Classes_A {}Note here, we don’t use namespaces.

The following composer.

json is working as expected and any namespace prefix App will look for the file inside the Classes directory, but with psr-0 you will find it confusing and will not work as expected:{ "autoload": { "psr-4": { "App" : "Classes" } }}5.

ConclusionWe have started defining the Autoloading in PHP and the problem that it is solving, then, we have built our simple one and finally, we have moved to talk about the composer and how it is doing the mapping in different ways.

The main reason I have introduced this topic that we are using composer in most of our applications and packages, and we have to understand how autoload section is working.

I tried to make it simple as much as I can, you can go further with the links below and if you have any question, just leave it in a comment.

6.

Referenceshttp://php.

net/manual/en/language.

oop5.

autoload.

phphttp://php.

net/manual/en/function.

spl-autoload-register.

phphttp://php.

net/manual/en/function.

get-included-files.

phphttps://getcomposer.

org/doc/04-schema.

md#autoloadhttps://www.

php-fig.

org/psr/psr-0https://www.

php-fig.

org/psr/psr-4.. More details

Leave a Reply