Namespaces
/**
* Two libraries might have classes with the same name.
* To prevent name collisions we use namespaces.
*
* Namespaces are a way to group classes, interfaces, functions and constants
* under a common name.
*
* To define a namespace we use the keyword 'namespace'
*/
namespace Google {
class Logger {
public function log($message) {
echo "Google: " . $message . PHP_EOL;
}
}
}
namespace Yahoo {
class Logger {
public function log($message) {
echo "Yahoo: " . $message . PHP_EOL;
}
}
}
namespace {
// Global namespace
$google = new \Google\Logger();
$google->log("Hello World!"); // Google: Hello World!
$yahoo = new \Yahoo\Logger();
$yahoo->log("Hello World!"); // Yahoo: Hello World!
}
Using namespaces
/**
* We can use a fully qualified name (with a leading backslash \) or
* import them with keyword 'use'.
*/
require 'vendor/Google/Logger.php';
require 'vendor/Yahoo/Logger.php';
$google = new \Google\Logger();
$google->log("Hello World!"); // Google Logger: Hello World!
$yahoo = new \Yahoo\Logger();
$yahoo->log("Hello World!"); // Google Logger: Hello World!
/**
* vendor/Google/Logger.php
*/
namespace Google;
class Logger {
public function log($message) {
echo "Google Logger: " . $message . "\n";
}
}
/**
* vendor/Yahoo/Logger.php
*/
namespace Yahoo;
class Logger {
public function log($message) {
echo "Yahoo Logger: " . $message . "\n";;
}
}
Autoloading via PSR-4
/**
Using autoloading via PSR-4.
This is the standar way to load classes without requiring each file manually.
Project structure:
my_project/
vendor/
VendorA/
Logger.php
VendorB/
Logger.php
autoload_spl.php
autoload_via_psr4.php
*/
require("autoload_custom.php");
use vendorA\Logger as LoggerA; // alias
use vendorB\Logger as LoggerB;
$loggerA = new LoggerA();
$loggerA->log("Logging with vendorA");
$loggerB = new LoggerB();
$loggerB->log("Logging with vendorB");
/**
> php autoload_via_psr4.php
VendorA Logger: Logging with vendorA
VendorB Logger: Logging with vendorB
*/
./autoload.php
/**
This autoloader automatically converts namespace paths into file paths
and include them dynamically.
*/
function classAutoLoader($class) {
// Convert namespace to full file path
$file = __DIR__ . '/vendor/' . str_replace("\\", "/", $class . ".php");
if (file_exists($file)) {
require $file;
}
}
spl_autoload_register("classAutoLoader");
Autoloading via Composer
/**
Instead of manually creating autoload.php, we can use Composer for PSR-4 autoloading.
This method is more scalable and aligns with modern PHP development.
Create composer.json:
> composer init
Then, modify composer.json to include:
{
...
"autoload": {
"psr-4": {
"VendorA\\": "vendor/vendorA/",
"VendorB\\": "vendor/vendorB/"
}
}
}
Run composer autoload:
> composer dump-autoload
Project structure will be:
my_project/
vendor/
composer/
autoload_psr4.php
autoload_real.php
...
VendorA/
Logger.php
VendorB/
Logger.php
autoload.php
autoload_via_composer.php
*/
require "vendor/autoload.php"; // Now using Composer's autoload
use vendorA\Logger as LoggerA; // Uppercase paths
use vendorB\Logger as LoggerB;
$loggerA = new LoggerA();
$loggerA->log("Logging with vendorA");
$loggerB = new LoggerB();
$loggerB->log("Logging with vendorB");
/**
> php autoload_via_composer.php
VendorA Logger: Logging with vendorA
VendorB Logger: Logging with vendorB
*/
./vendor/composer/autoload_psr4.php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'vendorB\\' => array($vendorDir . '/vendorB'),
'vendorA\\' => array($vendorDir . '/vendorA'),
);
Namespaces Theory
A namespace must be declared before any other code. Once defined, the scope of the namespace applies to the entire file. For global namespace, use the namespace keyword without a name. This feature can only be used in conjunction with the curly bracket syntax.
namespace MyProject {
// MyProject namespace ...
}
namespace {
// Global namespace ...
}
A fully-qualified namespace is like an absolute path in a file system.
A qualified name is like a relative path in a file system.
$a = new \myRoot\myLibrary\classes\myClass; // fully-qualified
$b = new myRoot\myLibrary\classes\myClass;
To reference classes in the global namespace, you must begin with backslash.
The functions do not need backslash.
namespace myLibrary\classes;
$obj = new ArrayObject(); // Fatal error: Class not found
$obj = new \ArrayObject(); // Look here
echo strlen("Hello World"); // Corect, resolves to native function
In a large application it can become cumbersome to write out identifier names.
You can import namespaces, classes and interfaces using the use keyword.
use com\yahoo as y; // Look Here
use com\google as g;
Questions and answers:
Clink on Option to Answer
1. How do you define a namespace?
- a) namespace google\Logger
- b) namespace google
- c) use vendor\google
2. What is the scope of namespaces?
- a) dinamically includes classes
- b) prevent class name collisions
3. How do you reference a class using namespaces?
- a) use google\Logger as Logger
- b) namespace google
- c) require("autoload.php")
4. How do you reference a class in the global namespace?
- a) \ArrayObject()
- b) ArrayObject
5. How do you import classes using namespaces?
- a) require("vendor/google/Logger")
- b) require("autoload.php")