When building small PHP scripts, everything seems simple - you write a few classes and functions, and they work fine. But as projects grow, especially in large-scale applications or when working with third-party libraries, name collisions become a real problem.
This is where namespaces come into play. Namespaces help organize and structure code, avoiding conflicts and improving readability.
What are Namespaces?
Think of a namespace as a container or folder for your code. Just like your operating system organizes files into directories to avoid conflicts, PHP organizes classes, functions, and constants into namespaces.
For example:
namespace App\Controllers; class UserController { public function index() { echo "User Controller"; } }
Here, the UserController class belongs to the namespace App\Controllers. This prevents clashes with another UserController that might exist elsewhere in your project or in an external library.
Why use Namespaces?
Namespaces solve several problems:
- Avoiding Name Collisions
- Better Code Organization
- Improved Autoloading
- Readability & Maintainability
Declaring a Namespace
Declaring a namespace is simple. At the top of your PHP file:
namespace MyApp\Models; class Product { public function __construct() { echo "Product model initialized."; } }
Now, this class is uniquely identified as:
MyApp\Models\Product
Using Namespaced Classes
If you want to use this class elsewhere, you have two options:
- Full Qualified Name (FQN)
require 'Product.php'; $product = new \MyApp\Models\Product();
Here, we use the backslash (\) to reference the global namespace and then specify the full namespace path.
- Import with use Keyword
require 'Product.php'; use MyApp\Models\Product; $product = new Product();
This is cleaner and preferred in larger applications.
Sub-namespaces
Namespaces can be nested, like folders:
namespace MyApp\Services\Mail; class Mailer { public function send($message) { echo "Sending: $message"; } }
Now, this class is fully qualified as:
MyApp\Services\Mail\Mailer
Grouping Imports
Group use declarations can reduce repetitive code:
use MyApp\Models\{User, Product, Order}; $user = new User(); $product = new Product(); $order = new Order();
This avoids writing multiple use lines.
Global Namespace
By default, PHP code resides in the global namespace (no namespace declared).
For example:
class Logger { public function log($msg) { echo $msg; } }
If you want to explicitly refer to this global class from within a namespace, use a leading backslash:
namespace MyApp; $logger = new \Logger(); // refers to global Logger class
Namespaces and Functions/Constants
Namespaces are not limited to classes - you can also namespace functions and constants:
namespace MyApp\Utils; function formatDate($date) { return date('Y-m-d', strtotime($date)); } const VERSION = '1.0.0'; // Usage echo \MyApp\Utils\formatDate('now'); echo \MyApp\Utils\VERSION;
Autoloading with Namespaces (PSR-4)
Namespaces are especially powerful with autoloading.
Following PSR-4 standard:
- Namespace maps to directory structure.
- Example.
Namespace: App\Controllers
Directory: src/Controllers/
Composer's autoload section in composer.json:
"autoload": { "psr-4": { "App\\": "src/" } }
This way, you don’t need to manually require files - autoloading resolves them automatically.
Common Mistakes with Namespaces
Real-World Example
Imagine two libraries define a class named PDF. Without namespaces, you'd have a conflict.
// Library 1 namespace Lib\PDF; class PDF {} // Library 2 namespace Vendor\PDF; class PDF {}
Now you can use both in the same project:
use Lib\PDF\PDF as LibPDF; use Vendor\PDF\PDF as VendorPDF; $doc1 = new LibPDF(); $doc2 = new VendorPDF();
Aliases (as) solve naming conflicts elegantly.
Source: Orkhan Alishov's notes