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")


References: