Intermediate · 50 MINUTES · VERSION 1
PHP namespaces and Composer PSR-4 autoloading
Separate class names, aliases, paths and dependency resolution with a real isolated Composer example.
Reviewed 23 Oct 2026Your setup may differ. Windows, Ubuntu, and optional tool bundles →
What you will learn
- Distinguish a qualified class name, file path and short alias.
- Map namespace prefixes with Composer PSR-4.
- Reproduce from a lock and investigate a missing class.
Theory: names are not file loading
A namespace gives a class a qualified name. Two classes can share the short name Session when their full names differ. A use statement introduces a local alias; it does not copy a class or include its file. An autoloader locates definitions when PHP needs them.
Composer generates an autoloader from project metadata. A PSR-4 prefix points at a base directory. Remaining namespace segments map to subdirectories; the class name maps to its PHP filename. Names and paths must match case. Windows can hide a filesystem case mistake that fails on Ubuntu.
This matters in Laravel: namespaces, container bindings, class names and file loading have different jobs. An editor recognizing a name is not proof that the running program can load it.
Worked example: two Session classes
Required: PHP 8.4+ and Composer. Create a new personal autoload-demo folder. Use these exact paths. There are no external packages. Laragon/XAMPP are optional; Composer must use compatible PHP. Do not change this website’s composer.json.
composer.json
{
"name": "study/autoload-demo",
"description": "A local dependency-free PSR-4 learning fixture.",
"type": "project",
"license": "MIT",
"require": {
"php": "^8.4"
},
"autoload": {
"psr-4": {
"StudyLab\\": "src/",
"StudyOther\\": "other/"
}
},
"config": {
"allow-plugins": false
}
}
src/Session.php
<?php
declare(strict_types=1);
namespace StudyLab;
final class Session
{
public function label(): string
{
return 'named learning session';
}
}
other/Session.php
<?php
declare(strict_types=1);
namespace StudyOther;
final class Session
{
public function label(): string
{
return 'independent namespace';
}
}
run.php
<?php
declare(strict_types=1);
use StudyLab\Session as LearningSession;
use StudyOther\Session as OtherSession;
require __DIR__.'/vendor/autoload.php';
echo 'Core: '.(new LearningSession)->label().PHP_EOL;
echo 'Other: '.(new OtherSession)->label().PHP_EOL;
Run and understand the output
Windows PowerShell, inside your new autoload-demo folder:
php --version
composer --version
composer install --no-plugins --no-scripts
php ./run.php
Ubuntu Bash, inside your new autoload-demo folder:
php --version
composer --version
composer install --no-plugins --no-scripts
php ./run.php
Core: named learning session
Other: independent namespace
Commands assume PHP/Composer on PATH. A fresh example creates composer.lock and vendor. Keep the generated lock with your practice source; later checkouts use install. The tracked fixture includes its lock. Do not copy Windows vendor to Ubuntu.
Run requires the generated autoloader using its own directory. Each alias constructs a different qualified class. The fixture was installed offline in an isolated Windows folder. Ubuntu execution is not claimed.
Lockfiles and dependency boundaries
composer.json declares requested rules; composer.lock records resolved dependencies. Install uses an existing lock; update intentionally resolves again and may change it. A lock supports reproducibility, but does not guarantee security or compatible extensions on every machine. Review changes and test them.
Plugins and script hooks can run code. This trusted fixture has no packages, disables plugins and uses no-plugins/no-scripts flags. The checker isolates Composer home/cache and disables networking. This does not make arbitrary downloaded projects safe. Never repair a mapping by editing vendor/autoload.php.
Guided lab
- Trace StudyLab\Session to src/Session.php and the second prefix to other/Session.php.
- Identify each full name, alias and output line.
- In a disposable copy, point a prefix at a missing directory. Observe failure, then restore it.
- Change an alias and its call site only; the declared class/path stays the same.
- Run composer validate --strict. After a mapping change run composer dump-autoload --no-plugins --no-scripts. Record the actual result, not a predicted pass.
Independent exercise
Add StudyLab\Reports\Summary in src/Reports/Summary.php with line() returning a dummy sentence. Call it from run.php without manually requiring that class file. Verify exact path/name case and that a genuinely absent class is not found. Hint: the existing prefix covers a longer namespace suffix when its directories match.
Common mistakes and interview
Avoid confusing use with require, wrong JSON backslash escaping, inconsistent case, Composer in the wrong project, update on every release and manual edits to generated files.
Interview: explain the full class name, namespace prefix, base directory, generated loader and missing-class investigation. Explain what the lock reproduces and what it cannot guarantee.
English practice and glossary
Namespace: a qualifier for names. Alias: a local short name. Autoloading: finding definitions when needed. PSR-4: a namespace/path convention. Lockfile: resolved dependencies. Generated file: tool-maintained output.
Write: “The full class name is __. The prefix maps to __. I reproduced the error by __ and fixed __.” Save dummy paths and evidence in your journal.
Recap and next step
Keep names, loading and dependency resolution distinct. Reproduce from locks; fix source metadata instead of generated vendor files. Next study enum values and explicit transition rules.
Reveal exercise hints and self-check answers
Use creates an alias; require executes a specified file. The generated loader maps a requested class to its configured path. Session names do not collide because their namespaces differ. Exact case matters even when a local filesystem forgives a mistake.
Exercise outline: create Reports/Summary.php with the matching namespace/class, add a use alias in run.php and call line(). The existing prefix covers it. Keep the lock and regenerate metadata when appropriate.