Skip to content

Namespaces and autoloading explained

In a project with third-party libraries there are bound to be several classes called “Client” or “Logger”. Namespaces solve this — and autoloading ensures that nobody has to include files by hand any more.

  • AudienceDevelopers, technically interested readers
  • LevelIntermediate
  • Reading timeabout 6 minutes
  • Last updated16 October 2026

What you will learn

  • What a namespace is and how it is written
  • What use statements do — and what they do not
  • How autoloading translates a class name into a file path
  • The two most common causes of “Class not found”

A namespace is a surname for classes

Without namespaces, each class could exist only once per application. Since every project uses third-party libraries today, that would be untenable. A namespace puts a path in front of the class name.

PHPtested with PHP 8.3
// File: src/Auftrag/Position.php
declare(strict_types=1);

namespace Firma\Shop\Auftrag;

final class Position
{
    // ...
}

// The fully qualified name is now:
// Firma\Shop\Auftrag\Position
The namespace goes at the very top, after declare. It has nothing to do with the file name — the connection is only made by autoloading.

A second class `Position` in a different namespace is no problem, because the fully qualified name is different.

use shortens names, it loads nothing

PHPtested with PHP 8.3
declare(strict_types=1);

namespace Firma\Shop\Rechnung;

use Firma\Shop\Auftrag\Position;
use Firma\Lager\Position as Lagerposition;

final class Rechnungszeile
{
    public function __construct(
        private readonly Position $position,
        private readonly ?Lagerposition $bestand = null,
    ) {
    }
}
Two classes with the same short name can be used side by side via “as”.

A common misconception: `use` does not include a file. It only defines which fully qualified name is meant when the short one appears in the code. The file is loaded only on first access — by autoloading.

Autoloading: from name to file path

In the past, every file began with a series of `require` lines. Today you register a function that PHP calls as soon as an unknown class is needed. In practice, Composer handles this according to the PSR-4 convention: a namespace prefix is mapped to a directory, and the rest of the name to the path beneath it.

JSONcomposer.json, excerpt
{
    "autoload": {
        "psr-4": {
            "Firma\\Shop\\": "src/"
        }
    }
}
Firma\Shop\Auftrag\Position thus becomes src/Auftrag/Position.php. After a change here, composer dump-autoload is required.

The mapping is literal: upper and lower case matter, because the file system on the server distinguishes them — even if your own machine perhaps does not.

An example from practice

“Class not found” — “Class not found” — four typical causes: namespace and path do not match; the mapping is new and Composer does not know it yet; a use statement is missing or a global class is referenced inside the namespace without a leading backslash; vendor/ was not installed.

  • The namespace in the file does not match the path. `namespace Firma\Shop\Auftrag;` in `src/auftrag/Position.php` works on your own machine and fails on the server.
  • The mapping is new and Composer does not know about it yet. After every change to `autoload` in `composer.json`, `composer dump-autoload` must be run.

A third, rarer cause is the optimised autoloader: `composer dump-autoload -o` creates a fixed list of all classes. A class whose path does not match the rule is missing from it — and is only noticed in the production environment, because optimisation is used there and not on the development machine.

Common misconceptions

No, it only shortens the name. Loading is done by the autoloader on first access.

The language does not require it. The PSR-4 convention, and therefore Composer, does — and practically every project follows it.

Only on the first access to a class, and the optimised autoloader turns that into a lookup in a ready-made list.

Further sources

About the author

Fabian Lücker is managing partner of PHP-Schmiede KG in Rheine and has worked in software development since 2007. He is responsible for development and design, and writes here about decisions that arise in real projects.