PHP Namespaces
This is a bonus page that pairs naturally with OOP. As soon as a project combines code from several places — your own classes plus one or more third-party libraries — two authors will eventually pick the same class name. Namespaces solve that by giving classes an address, the same way folders let two files share a name as long as they live in different directories.
1) Why Namespaces Exist
Without namespaces, PHP keeps every class name in one single global list. If your code defines
a class Logger and a library you installed also defines a class Logger,
PHP cannot tell them apart — loading both causes a fatal
“Cannot declare class Logger, because the name is already in use” error.
2) Declaring a Namespace
A namespace is declared with the namespace keyword as the very first statement
in a file (aside from an optional declare()).
<?php
namespace App\Models;
class User {
public string $name = '';
}
?>
The class above is really called App\Models\User, not just User.
Another file can freely declare a completely different Payments\User or
Legacy\User without any conflict.
3) Importing with use
Typing the full namespaced name everywhere gets verbose, so use imports a class
into the current file under a short alias (its own class name, by default).
<?php
namespace App\Controllers;
use App\Models\User;
$u = new User(); // resolves to App\Models\User
?>
4) Fully-Qualified Names
A name starting with a backslash, like \App\Models\User, is fully qualified
— it always points to that exact class no matter what namespace the current file is in.
This is handy for one-off references without adding a use line.
<?php
$u = new \App\Models\User();
?>
5) Live Demo: Two Same-Named Classes, Zero Conflict
A single PHP file normally can’t mix namespaced and non-namespaced code freely, but PHP does
support a bracketed namespace syntax that lets several namespaces (and the global
namespace) coexist in one file. This page uses exactly that at the very top of the file,
before <!DOCTYPE html>, to define two classes that are both called
Animal:
<?php
namespace Zoo {
class Animal {
public function type(): string { return 'Zoo Animal'; }
}
}
namespace Farm {
class Animal {
public function type(): string { return 'Farm Animal'; }
}
}
namespace {
$z = new \Zoo\Animal();
$f = new \Farm\Animal();
echo $z->type();
echo $f->type();
}
?>
The two lines below are the real, live output of $zooAnimal->type() and
$farmAnimal->type() — two genuinely separate classes, both named
Animal, running side by side on this page without a single naming conflict:
| Fully-Qualified Class | Live Result of ->type() |
|---|---|
\Zoo\Animal |
Zoo Animal |
\Farm\Animal |
Farm Animal |
Zoo\Animal and Farm\Animal in their own separate files with a plain
namespace Zoo; / namespace Farm; declaration at the top — the
bracketed syntax above exists mainly so this one demo file could prove the collision-avoidance
live, in a single page.6) Autoloading with Composer (Conceptual Note)
In real-world projects, you don’t manually require every class file. Composer’s
PSR-4 autoloading maps a namespace prefix to a folder, so a class is loaded automatically
the first time it is used, based purely on its namespace matching a directory path. For example,
a composer.json mapping "App\\": "src/" means the class
App\Models\User is expected to live at src/Models/User.php —
no manual include needed. This is a conceptual note only; this tutorial site does not set up
or demonstrate an actual Composer autoloader.
connection.php,
track-visitor.php, and the tutorial pages) use plain global functions and
include/require statements. The site is small and predates needing
namespaces; they earn their keep once a project has enough files, or enough third-party
libraries, that name collisions become a real risk.7) Best Practices & Common Mistakes
| Issue | Problem | Fix |
|---|---|---|
| No namespace at all in a growing codebase | Class name collisions as the project or its dependencies grow | Adopt a namespace per logical module (e.g. App\Models, App\Controllers) |
| Forgetting the leading backslash | new Animal() inside a namespace resolves to that namespace’s class, not the global one | Use \Animal to explicitly target the global namespace |
| Mixing folder structure and namespace structure | Autoloaders like PSR-4 can’t find the class file | Keep namespace segments and folder names in sync |