Tweet
Share
Send by LINE
B! Bookmarks in Hate-bu
Bookmarks in Pocket
RSS feeds

PHP composer, Let's make the most of autoload !

PHP autoloading is the ability to define a 'use' operator to automatically load a class. It does not use the 'require' operator.

Autoloading is part of the 'composer' that manages PHP packages and is a necessary feature of PHP.

I will explain how to use it in a detailed and easy to understand manner.

This is written by a Japanese who can't speak English with the help of translation application. Sorry if it's not good.

What is autoloading?

Autoloading is the ability to use PHP classes without 'require' a class file, just defining a 'use' operator.

How to use the class without autoload
<?php
require "TestClass1.php";
require "TestClass2.php";
require "TestClass3.php";

use TestClass1;
use TestClass2;
use TestClass3;

$test1 = new TestClass1();
$test2 = new TestClass2();
$test3 = new TestClass3();
How to use autoload classes
<?php
require vendor/autoload.php

use TestClass1;
use TestClass2;
use TestClass3;

$test1 = new TestClass1();
$test2 = new TestClass2();
$test3 = new TestClass3();

I don't get an error when I don't have TestClass* written anywhere and I haven't imported TestClass*.php.

That's because TestClass* was already required by the autoload.

In object-oriented programming, we use a lot of classes. And there is a rule of 'one file, one class'.

If we don't have autoload, we have to write a lot of class file requirements. We have autoloading to avoid doing that.

Let's use autoload!

Let's use autoload before I explain. Just work in the same way.

First, install the composer in the PHP environment, because you can't use it without the composer.

Creating composer.json file

Go to the PHP project home. Here is 'user-test/php-test-autoload'.

...─ php-test-autoload
       ├─ (empty)

Still, the contents of the project are empty. Now run the command composers.

composer.json creation command
composer init

You will be asked for various inputs, but for now, just press the Enter key.

...─ php-test-autoload
       ├─ composer.json

There should be a composer.json in the home of the project.

composer.json
{
    "name": "user-test/php-test-autoload",
    "authors": [
        {
            "name": "user-test",
            "email": "user-test@gmail.com"
        }
    ],
    "require": {}
}

The 'authors' can be empty. It must be set in php.ini and will not be added.

Installation of the autoload package

The project only has a composer.json. Next, install the autoload package.

Autoload installation command
composer install

The autoload package has been installed.

...─ php-test-autoload
       ├─ vendor
       │    ├─ composer
       │    │    ├─ autoload_classmap.php
       │    │    ├─ autoload_namespaces.php
       │    │    ├─ autoload_psr4.php
       │    │    ├─ autoload_real.php
       │    │    ├─ autoload_static.php
       │    │    ├─ ClassLoader.php
       │    │    ├─ installed.php
       │    │    └─ LICENSE
       │    └─ autoload.php
       └─ composer.json

The vendor directory is the installation location for the packages to be added to the 'require' of composer.json.

Since autoload is a feature of the composer, it was installed in the 'vendor/composer' directory.

vendor/autoload.php

There is also a program that runs autoload? Just load it with the 'require' operator and you can autoload it.

Since autoload is a basic feature of the composer, it is always installed with the first 'composer install' command.

Same thing if composer.json's 'require' is empty.

The 'require' in compsoer.json is a list of packages to be installed in the project.

PHP sample program creation

The autoload package has been added to the project. Next, add the sample program to the project.

...─ php-test-autoload
       ├─ src
       │    ├─ main.php
       │    ├─ TestClass1.php
       │    ├─ Test2
       │    │    └─ TestClass2.php
       │    └─ Test3
       │         └─ TestClass3.php
       ├─ vendor
       │    ├─ composer
       │    │    ├─ autoload_classmap.php
       │    │    ├─ autoload_namespaces.php
       │    │    ├─ autoload_psr4.php
       │    │    ├─ autoload_real.php
       │    │    ├─ autoload_static.php
       │    │    ├─ ClassLoader.php
       │    │    ├─ installed.php
       │    │    └─ LICENSE
       │    └─ autoload.php
       └─ composer.json
TestClass1.php
<?php

namespace Origin;

class TestClass1 {
    function __construct() {
        echo "new instance TestClass1\n";
    }
}
TestClass2.php
<?php

namespace Origin\Test2;

class TestClass2 {
    function __construct() {
        echo "new instance TestClass2\n";
    }
}

Do the same for TestClass3; note the difference in namespace between TestClass1, TestClass2 and TestClass3.

It will come out later, but this time we will use psr4 coding conventions. psr4 has the following rules

  • Class files must have namespace.
  • The namespace should match the directory configuration and name.
  • Namespace names start with a capital letter.
PSR (PHP Standards Recommendations)

https://www.php-fig.org/psr/

A standardization effort for PHP coding, developed by PHP-FIG.

PHP-FIG (PHP Framework Interop Group)

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

PHP Framework Interoperability Group, an organization where PHP projects get together to discuss and coordinate the compatibility of each other's products.

Many famous projects are participating.

main.php
<?php

require "vendor/autoload.php";


use Origin\TestClass1;
use Origin\Test2\TestClass2;
use Origin\Test3\TestClass3;

new TestClass1();
new TestClass2();
new TestClass3();

Editing composer.json

Register the directory where the class files are located, so that autoload can get them.

Registration is done with the composer's configuration file, composer.json.

Register autoload to composer.json
{
    "name": "user-test/php-test-autoload",
    "authors": [
        {
            "name": "user-test",
            "email": "user-test@gmail.com"
        }
    ],
    "require": {},
    "autoload": {
        "psr-4": {
            "Origin\\": "src/"
        }
    }
}

In autoload{}, the class files in the src directory are registered to begin with 'Origin'.

In psr4, namespace names must start with a capital letter, so 'src' cannot be used.

Here, when loading the class, we convert 'src' to 'Origin' to match the namespace.

Match directory configuration and namespace configuration

The composer.json will be updated when you install the package using composer.

The class of the package is automatically added to the autoload{}. You do not have to work by yourself.

This time, I edited it directly in my own program and not in the composer package.

If you edit composer.json directly, you must execute the following command.

composer validate

This is the composer.json syntax check command. If you get an error, your edits are wrong.

Be careful, as you will not be able to use composer commands.

Updating the autoload map file

Update autoload.

autoload update command
composer update

This updates the settings in composer.json to be precise. Since we added autoload{}, this will also update autoload.

The mechanism of autoload is simple.

composer install

composer update

composer require

Execute this command to create and update the map file.

The contents of the map file is just an array, in which the classes and namespaces are defined.

Autoload doesn't load a class, it just refers to the defined class.

...─ php-test-autoload
       └─ vendor
            └─ composer
                 ├─ autoload_classmap.php
                 ├─ autoload_namespaces.php
                 ├─ autoload_psr4.php
                 ├─ autoload_static.php
                 └─ installed.php

You saw earlier, these files of autoload are map files.

The autoload registration of psr4 in composer.json will be updated like this

autoload_psr4.php
<?php

// autoload_psr4.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'Origin\\' => array($baseDir . '/src'),
);

The conversion 'src' -> 'Origin' is registered in the map.

When the composer command updates the composer.json file, it expands the contents defined in autoload{} to the autoload map file.

vendor/autoload.php is a summary of all the map files. So only 'require'.

Let's run the program!

The autoload sample program is now complete. Let's run it.

Execution Confirmation
php src/main.php
new instance TestClass1
new instance TestClass2
new instance TestClass3

If you run it in the home of the project and get the same result, the usage of autoload is OK.

Updating the autoload map

Earlier, we updated the map file with this command.

composer update

But this command is for updating the composer.json file, not for updating the map.

For example, when you add the source code, the class is not registered in the map.

The composer.json has not been edited, so the "composer update" command will not work either.

In that case, use the following command.

The autoload map update command
composer dump-autoload

This reconstructs the autoload map only.

Class not Found

Let's do this once it occurs.

Surprisingly, sometimes it is not a bug in the program, but just the map is not updated.

Be careful when using 'dump-autoload -o'

Autoload has a map optimization feature called 'Autoloader Optimization' for fast loading.

Speeding up autoload
composer dump-autoload -o

'-o' option. But be careful.

With this option, the rules of psr-4 will be ignored when rebuilding the class map.

Class files with namespace and directory configurations that do not conform to psr-4 will also be registered in the class map.

You may suddenly get a lot of "Class not Found".

This happens when you are updating a map with options and one time you update it without options. Surprisingly, this pattern is very common.

It should be noted that this is a common occurrence in Laravel.

Development EnvironmentNo options
Production EnvironmentOptional

It is better to use this usage.

Non-class can also autoload

Autoload can autoloading even outside of classes.

  • interface
  • function
  • const
A variety of autoload
<?php
require vendor/autoload.php;

use My\Full\ClassName as ClassName;
use My\Full\InterfaceName as IFName;

class Test extends ClassName implements IFName {
    // ...
}
 
// >= PHP 5.6
use function My\Full\functionName as func;

$ret = func();
 
// >= PHP 5.6
use const My\Full\CONSTANT CONST_A;

$val = CONST_A;

However, function and const are only supported by PHP version 5.6 or later.

Laravel is already in

The PHP web framework Laravel includes a composer.

There is also composer.json and the autoload package in vendor/composer.

require vendor/autoload.php

This is also not necessary. It is already implemented in public/index.php.

Summary of autoload

  • Write "require vendor/autoload.php" only once in the source code.
  • The use operator allows classes, interfaces, functions and const to be autoloaded.
  • Write the configuration in the composer.json file.

This is the only basic usage of autoload.

I'd like to say "this is the end", but I'll continue with the advanced part.

Didn't you also describe the psr4 used in composer.json's autoload{} ?

Other methods of specification are also described.

The types specified in autoload

The composer.json's autoload{} can be specified in a variety of ways other than psr-4.

Let's take a look at them one by one.

files

"autoload": {
    "files": [
        "src/functions/func1.php",
        "src/const/const1.php",
    ]
}

Autoload functions and const from .php files. Use it outside of classes and interfaces.

Map files

vendor/composer/autoload_files.php

psr-4

"autoload": {
    "psr-4": { "Vendor\\": "src/vendor/" }
}
Multiple specifications
"autoload": {
    "psr-4": { "Vendor\\": ["src/Vendor/", "lib/Vendor/"] }
}

Use in Laravel and other psr-compliant ones.

The psr-4 namespace and directory configuration should match.

Specify the directory location of its top-level namespace directory.

You can also specify more than one, enclosed in [].

In PHP it is normal to conform to the PSR, and it is rare not to participate like in WordPress.

However, there are many projects that do not participate.

When the namespace and directory configuration do not match in psr-4, an error occurs during application execution.

Class not Found

The error of the package itself does not occur, so it looks as if the application has a bug.

The map information in autoload may be outdated or a bug in the package.

psr-4 also includes what you set up in psr-0.

No need for psr-0 settings, which will be explained later.

Map files

vendor/composer/autoload_psr-4.php

vendor/composer/autoload_static.php

vendor/composer/autoload_classmap.php

psr-0

"autoload": {
    "psr-0": {
        "Vendor\\": "src/Vendor/",
        "Vendor\\Namespace\\": "src/Vendor/",
        "Vendor_Namespace_": "src/"
    }
}

The current level of psr is predominantly 4.

Since larger psr levels include lower levels, psr-0 is rarely used.

Use it with older source code, such as projects that have been around for a few years, or those that are up to psr-2 compliant.

There is no psr-2 in composer autoload.

Map files

vendor/composer/autoload_classmap.php

classmap

"autoload": {
    "classmap": ["src/", "lib/", "Something.php"]
}

Use when not complying with psr, such as WordPress.

Map files

vendor/composer/autoload_classmap.php

exclude-from-classmap

"autoload": {
    "exclude-from-classmap": ["/Tests/", "/test/", "/tests/"]
}

Set the autoload exclusion.

Specify classes that are not used in the production environment, such as test classes.

Map files

vendor/composer/autoload_classmap.php

Development environment autoload

Set the autoload of the development environment.

Specify the test class and so on. The only directory that can be specified is the root directory.

Leave a Reply

*