Kodokon kodokon.com

Namespaces, autoloading and Composer

Structure your code with PSR-4 namespaces and let Composer load classes and dependencies for you.

8 min · 3 questions

Open this lesson in Kodokon

Namespaces eliminate name collisions: two libraries can each define a Client class without conflict. The universal convention: a vendor prefix (App, Acme\Blog), then sub-namespaces that mirror the folder tree. use imports a fully qualified name into the current file, as renames it in case of ambiguity. One file = one class = one namespace: this discipline isn't a stylistic quirk, it's the very condition for autoloading.

PHP
<?php

declare(strict_types=1);

namespace App\Service;

use App\Repository\UserRepository;
use Psr\Log\LoggerInterface as Logger;

final class UserService
{
    public function __construct(
        private UserRepository $users,
        private Logger $logger,
    ) {
    }
}
A src/Service/UserService.php file: namespace, imports, alias.

Autoloading loads class files on demand: no more manual require. The PSR-4 standard defines the mapping: a namespace prefix is associated with a root folder, and each sub-namespace becomes a subfolder. App\Service\UserService thus resolves to src/Service/UserService.php. Under the hood, everything relies on spl_autoload_register - here is the minimal implementation, worth understanding even if you never rewrite it:

PHP
<?php

declare(strict_types=1);

spl_autoload_register(function (string $class): void {
    $prefix = 'App\\';
    $baseDir = __DIR__ . '/src/';

    if (!str_starts_with($class, $prefix)) {
        return;
    }

    $relative = substr($class, strlen($prefix));
    $path = $baseDir
        . str_replace('\\', '/', $relative)
        . '.php';

    if (is_file($path)) {
        require $path;
    }
});

echo 'Autoloader registered';
Handcrafted PSR-4 autoloader: prefix, root folder, conversion to a path.

Composer industrializes all of this: composer.json declares your dependencies and your PSR-4 mapping - typically "autoload": { "psr-4": { "App\\\\": "src/" } } - then composer install downloads the packages into vendor/ and generates vendor/autoload.php, the single require of your entire application. Essential distinction: require for packages needed in production, require-dev for tooling (tests, static analysis), excluded from deployments with --no-dev.

BASH
composer init --name acme/app --no-interaction
composer require monolog/monolog
composer require --dev phpunit/phpunit
composer dump-autoload -o
Lifecycle: initialize, add dependencies, regenerate the autoloader.

Knowledge check

Make sure you remember the key points of this lesson.

  1. According to PSR-4, where is the class App\Blog\PostRepository located if the App\ prefix points to src/?
    • src/App/Blog/PostRepository.php
    • src/Blog/PostRepository.php
    • src/blog/postrepository.php
  2. Which file should you include to benefit from the autoloading generated by Composer?
    • composer.json
    • vendor/autoload.php
    • an autoload.php to create at the root
  3. What is composer require --dev for?
    • Installing a development-only package, excluded from deployments with --no-dev
    • Installing an unstable version of the package
    • Installing the package globally on the machine