Lesson 12 / 25

Namespaces, Autoloading and Composer Packages

Organise code with namespaces and PSR-4 autoloading, and manage dependencies.

From include files to packages

Old PHP code used long chains of require statements. Modern PHP organises classes into namespaces that mirror directories: namespace Shop\Orders; in src/Orders/. Import names with use statements (use Shop\Payments\PaymentGateway;), with aliases when names clash. PSR-4 autoloading maps a namespace prefix to a directory, so Shop\Orders\OrderService loads src/Orders/OrderService.php automatically the first time it is used; Composer generates the autoloader, and you include vendor/autoload.php once at your entry point. Keep one class per file, with the file name matching the class name. Third-party code comes from Packagist via Composer, using semantic version constraints: ^3.2 allows 3.x updates but not 4.0. Run composer audit to check installed packages for known vulnerabilities, composer outdated to see available updates, and keep require-dev packages (PHPUnit, PHPStan) out of production installs with composer install --no-dev.

Namespaces with PSR-4 autoloading

The directory layout matches namespaces, so no require statements are needed.

// composer.json
// {
//   "require": { "php": "^8.3", "monolog/monolog": "^3.5" },
//   "autoload": { "psr-4": { "Shop\\": "src/" } }
// }

// src/Orders/OrderService.php
<?php
declare(strict_types=1);

namespace Shop\Orders;

use Psr\Log\LoggerInterface;
use Shop\Payments\PaymentGateway;

final class OrderService
{
    public function __construct(
        private readonly PaymentGateway $payments,
        private readonly LoggerInterface $logger,
    ) {}
}

// public/index.php
<?php
require __DIR__ . '/../vendor/autoload.php';
$service = new Shop\Orders\OrderService($gateway, $logger);   // loaded automatically

// composer audit        # known vulnerabilities in dependencies

Type against PSR interfaces

Depend on Psr\Log\LoggerInterface, Psr\Http\Client\ClientInterface or Psr\SimpleCache\CacheInterface instead of a specific library class. You can then swap Monolog for another logger without touching your code.

Quick check: With PSR-4 mapping "Shop\\" to "src/", where should the class Shop\Orders\OrderService live?

  • src/Orders/OrderService.php
  • src/OrderService.php
  • Shop/Orders.php
  • vendor/Shop/OrderService.php
Answer

src/Orders/OrderService.php — PSR-4 maps the namespace segments after the prefix onto directories under src/.