Namespaces and Autoloading

Course 2 · Ch 6
Namespaces and Autoloading: PSR-4, Composer Basics
Avoiding class-name collisions, and letting PHP find and load classes automatically instead of writing require_once everywhere

Chapter 9 of the Fundamentals course used require_once to manually pull in every file defining a class or function. That works fine for a handful of files, but becomes unmanageable in a larger project with dozens of classes. Namespaces and autoloading — almost always set up via Composer — solve this properly, and are the standard approach in essentially all modern PHP projects.

The Problem: Class Name Collisions

<?php // library_a.php defines: class Logger { /* ... */ } // library_b.php ALSO defines: class Logger { /* ... */ } // fatal error if both files are loaded — "Cannot redeclare class Logger" ?>

If two different libraries both happen to define a class called Logger, including both in the same project is a fatal error. With many third-party packages in use, name collisions like this become a genuine, recurring problem without some way to keep names separated.

Namespaces — Solving the Collision Problem

src/Acme/Logger.php
<?php namespace Acme; class Logger { public function log(string $message) { echo "[Acme] $message<br>"; } } ?>
src/Vendor/Logger.php
<?php namespace Vendor; class Logger { public function log(string $message) { echo "[Vendor] $message<br>"; } } ?>
index.php
<?php use Acme\Logger as AcmeLogger; use Vendor\Logger as VendorLogger; $logger1 = new AcmeLogger(); $logger2 = new VendorLogger(); $logger1->log("Hello"); // "[Acme] Hello" $logger2->log("Hello"); // "[Vendor] Hello" ?>

Both classes are genuinely named Logger, but their full, unambiguous identities are Acme\Logger and Vendor\Logger — exactly like how two different files on a computer can both be called notes.txt as long as they live in different folders. use ... as ... imports a class under a shorter or renamed alias for convenience within one file.

Autoloading — No More require_once for Every Class

Namespaces solve naming collisions, but PHP still needs to know where a class's file actually is when new Acme\Logger() is used. Autoloading registers a function that PHP calls automatically the first time an unknown class name is referenced — that function works out the file path and includes it, with no manual require needed anywhere.

PSR-4 — The Standard Convention

PSR-4 is a widely-adopted convention mapping namespaces directly onto folder structures, so an autoloader can calculate a file's path purely from a class's namespace and name, without any manual configuration per class.

my-project/ src/ Acme/ Logger.php — namespace Acme; class Logger Database/ Connection.php — namespace Acme\Database; class Connection composer.json

The namespace Acme\Database\Connection maps directly onto the path src/Acme/Database/Connection.php — predictable enough that an autoloader can compute it instead of being told it explicitly for every single class.

Composer — Installing Packages and Generating the Autoloader

Composer is PHP's standard package manager — it downloads third-party libraries, and (genuinely just as importantly for this chapter) generates a working PSR-4 autoloader for your own project's classes too.

composer.json
{ "autoload": { "psr-4": { "Acme\\": "src/Acme/" } } }
$ composer dump-autoload # generates vendor/autoload.php — the single file every entry-point script needs
index.php
<?php require 'vendor/autoload.php'; // the ONLY require needed — handles every class automatically from here use Acme\Logger; $logger = new Logger(); // Composer's autoloader finds and includes src/Acme/Logger.php automatically $logger->log("Started"); ?>
composer require some/package — installing a real third-party library
Beyond autoloading your own code, composer require monolog/monolog (for example) downloads a library into a vendor/ folder and adds it to composer.json automatically — the same single require 'vendor/autoload.php' line then makes that library's classes available too, alongside your own.
vendor/ should never be committed to git
The vendor/ folder is regenerated entirely from composer.json by running composer install — committing it bloats a repository unnecessarily. A .gitignore entry for /vendor/ is standard practice in essentially every Composer-managed PHP project.

Coding Challenges

Challenge 1

Create two files, src/Shop/Product.php (namespace Shop; class Product with a $name property) and src/Warehouse/Product.php (namespace Warehouse; class Product with a $stockLevel property). In a third file, use both classes with aliases via use ... as ... and create one instance of each, demonstrating no naming collision occurs.

📄 View solution
Challenge 2

Write a composer.json defining a PSR-4 mapping for the namespace prefix "App\\" to a folder "app/". Describe in a comment which command would be run after creating/editing this file, and what it generates.

📄 View solution
Challenge 3

Design (in comments/text, not necessarily runnable) a small project structure with namespace App\Models containing a User class and App\Services containing an EmailService class, following PSR-4 folder conventions. Write the index.php that would use both via Composer's autoloader, with no manual require_once for either class.

📄 View solution

Chapter 6 Quick Reference

  • namespace Acme; — gives every class in the file a fully-qualified identity (Acme\ClassName), avoiding collisions
  • use Acme\Logger as AcmeLogger; — imports/aliases a class for convenient use within a file
  • Autoloading — PHP calls a registered function automatically to find/include a class's file on first use
  • PSR-4 — standard convention mapping namespaces directly onto folder structures
  • composer.json "autoload"/"psr-4" — declares the namespace-to-folder mapping
  • composer dump-autoload — (re)generates vendor/autoload.php from that mapping
  • require 'vendor/autoload.php'; — the one require needed; handles every class from then on
  • vendor/ should never be committed to git — regenerate via composer install
  • Next chapter: working with JSON and APIs — json_encode/decode, consuming a REST API with cURL