PHP Namespace Full (ok)

https://www.phptutorial.net/php-oop/php-namespace/

C:\xampp\htdocs\wpclidemo\index-error.php

<?php
require 'src/Model/Customer.php';
$customer = new Customer('Bob');
echo $customer->getName();
?>

C:\xampp\htdocs\wpclidemo\index.php

<?php
// require 'src/Model/Customer.php';
// Part ================================================================== 1
// $customer = new Store\Model\Customer('Bob');
// echo $customer->getName(); // Bob
// Part ================================================================== 2
// $customer = new Model\Customer('Bob');
// echo $customer->getName(); // Bob
// Part ================================================================== 3
// use Store\Model\Customer;
// $customer = new Customer('Bob');
// echo $customer->getName(); // Bob
// Part ================================================================== 4
// require 'src/Model/Product.php';
// use Store\Model\Customer;
// use Store\Model\Product;
// $customer = new Customer('Bob');
// echo $customer->getName();
// $product = new Product();
// Part ================================================================== 5 use namespace\{className1, className2, ...}
// require 'src/Model/Customer.php';
// require 'src/Model/Product.php';
// use Store\Model\{Customer, Product};
// $customer = new Customer('Bob');
// echo $customer->getName();
// $product = new Product();
// Part ================================================================== 6 Use classes from the global namespace
// $publish_at = new \DateTime();
// echo $publish_at->format('Y-m-d H:i:s'); // 2022-06-17 07:56:06
?>

C:\xampp\htdocs\wpclidemo\src\Model\Customer.php

<?php
namespace Store\Model;
class Customer {
  private $name;
  public function __construct($name) {
    $this->name = $name;
  }
  public function getName() {
    return $this->name;
  }
}

C:\xampp\htdocs\wpclidemo\src\Model\Product.php

<?php
namespace Store\Model;
class Product {
}

Summary: in this tutorial, you’ll learn about PHP namespaces, how to define classes that belong to a namespace, and how to use namespaces.

Why namespaces

When your project grows in complexity, you’ll need to integrate the code from others. Sooner or later, you’ll find that your code has different classes with the same name. This problem is known as name collision.

To resolve it, you can use namespaces. PHP supported namespaces since version 5.3.

What is a namespace

It’s easier to understand namespaces by analogy to the directory structure in a filesystem.

A directory stores related files, which is similar to a namespace that groups related classes.

A directory doesn’t allow you to have two files with the same name. However, you can have files with the same names in different directories. Likewise, namespaces mimic the same principle.

By definition, namespaces provide you with a way to group related classes and help you avoid any potential name collisions.

Namespaces are not limited to group classes. They can group other identifiers, including functions, constants, variables, etc.

Set up a directory structure

First, create a project directory, e.g., store and create a new index.php file in the directory.

Second, create src directory in the project directory and Model directory in the src directory.

Third, create a new file called Customer.php in the Model directory with the following code:

<?php

class Customer
{
    private $name;

    public function __construct($name)
    {
        $this->name = $name;
    }

    public function getName()
    {
        return $this->name;
    }
}Code language: HTML, XML (xml)

The directory looks like the following:

.
├── index.php
└── src
    └── Model
        └── Customer.phpCode language: plaintext (plaintext)

Define a namespace

To define a namespace, you place the namespace keyword followed by a name at the very top of the page. The following example gives the Customer class with a namespace Store\Model:

<?php

namespace Store\Model;

class Customer
{
    private $name;

    public function __construct($name)
    {
        $this->name = $name;
    }

    public function getName()
    {
        return $this->name;
    }
}Code language: HTML, XML (xml)
  • It’s customary to assign the src directory the Store namespace. And you can replace Store with your brand name, e.g., Apple.

  • It’s a good practice to imitate the directory structure with the namespace to find classes more easily. For example, every class within the directory will get the namespace Store\Model.

Use a class that belongs to a namespace

To use a class that belongs to a namespace in the index.php, you need to include the file and use the class:

<?php

require 'src/Model/Customer.php';

$customer = new Customer('Bob');
echo $customer->getName();Code language: HTML, XML (xml)

If you open the index.php, you’ll get a fatal error:

Fatal error: Uncaught Error: Class 'Customer' not found in...
Code language: JavaScript (javascript)

Since the Customer class now is namespaced, you need to use the fully qualified name that includes the namespace like this:

<?php

require 'src/Model/Customer.php';

$customer = new Store\Model\Customer('Bob');
echo $customer->getName();Code language: HTML, XML (xml)

Now, it should work properly.

Import a namespace

To avoid using the fully qualified names from a namespace, you can import the namespace with the use operator like this:

<?php

require 'src/Model/Customer.php';
use Store\Model;

$customer = new Model\Customer('Bob');
echo $customer->getName();Code language: HTML, XML (xml)

Now, you just need to prefix the class name with Model.

Import a class from a namespace

PHP allows you to import a class from a namespace instead of importing the namespace. For example:

<?php

require 'src/Model/Customer.php';
use Store\Model\Customer;

$customer = new Customer('Bob');
echo $customer->getName();Code language: HTML, XML (xml)

In this example, we use the use operator to import the Customer class from the Store\Model namespace. Therefore, we don’t have to prefix the class name with the namespace.

Import multiple classes from a namespace

First, create a new file called Product.php in the src/Model directory:

<?php

namespace Store\Model;

class Product
{
}Code language: HTML, XML (xml)

For demonstration purposes, the Product class is empty. Now, the directory structure looks like the following:

.
├── index.php
└── src
    └── Model
        ├── Customer.php
        └── Product.phpCode language: plaintext (plaintext)

To use both Customer and Product classes from the index.php, you can import them individually like before:

<?php

require 'src/Model/Customer.php';
require 'src/Model/Product.php';

use Store\Model\Customer;
use Store\Model\Product;

$customer = new Customer('Bob');
echo $customer->getName();

$product = new Product();Code language: HTML, XML (xml)

When the number of imported classes grows, your code will become more verbose. So instead of importing each individual class, you can import all the classes using a single statement:

use namespace\{className1, className2, ...}Code language: PHP (php)

For example:

<?php

require 'src/Model/Customer.php';
require 'src/Model/Product.php';

use Store\Model\{Customer, Product};

$customer = new Customer('Bob');

echo $customer->getName();

$product = new Product();Code language: HTML, XML (xml)

Alias classes from a namespace

First, create a new directory called Database under the project directory and place a new file Logger.php in the Database directory with the following code:

<?php

namespace Store\Database;

class Logger
{
    public function log($message)
    {
        var_dump('Log ' . $message . ' to the database.');
    }
}Code language: HTML, XML (xml)

Second, create a new directory Utils under the project directory and create a new Logger.php in the Utils directory.

<?php

namespace Store\Utils;

class Logger
{
    public function log($message)
    {
        var_dump('Log ' . $message);
    }
}Code language: HTML, XML (xml)

Now, you have two classes with the same name in different namespaces:

.
├── index.php
└── src
    ├── Database
    │   └── Logger.php
    ├── Model
    │   ├── Customer.php
    │   └── Product.php
    └── Utils
        └── Logger.phpCode language: plaintext (plaintext)

Third, import Logger classes from both namespaces Store\Utils and Database\Logger into the index.php file:

<?php

require 'src/Utils/Logger.php';
require 'src/Database/Logger.php';

use Store\Utils\Logger;
use Store\Database\Logger;Code language: HTML, XML (xml)

PHP raises the following error:

Fatal error: Cannot use Store\Database\Logger as Logger because the name is already in use in...Code language: plaintext (plaintext)

To avoid this, you can just import the namespaces:

<?php

require 'src/Utils/Logger.php';
require 'src/Database/Logger.php';

use Store\Utils;
use Store\Database;

$loggers = [
    new Utils\Logger(),
    new Database\Logger()
];
Code language: HTML, XML (xml)

Or you can give a class an alias when importing it:

import namespace\className as newClassName;Code language: JavaScript (javascript)

The following example assigns the DatabaseLogger class an alias to the Store\Database\Logger class:

<?php

require 'src/Utils/Logger.php';
require 'src/Database/Logger.php';

use Store\Utils\Logger;
use Store\Database\Logger as DatabaseLogger;

$loggers = [
    new Logger(),
    new DatabaseLogger()
];Code language: HTML, XML (xml)

Use classes from the global namespace

To use global classes such as built-in classes or user-defined classes without a namespace, you need to precede the name of such classes with a backslash (\).

The following example shows how to use the built-in DateTime class in the App namespace:

<?php

namespace App;

$publish_at = new \DateTime();

echo $publish_at->format('Y-m-d H:i:s');Code language: HTML, XML (xml)

Summary

  • Use a namespace to group related classes.

  • Mimic the directory structure with the namespaces to make it easier to find the classes.

  • Use the use operator to import a namespace or a class from a namespace.

  • Use the as keyword to assign a namespace or a class of a namespace an alias.

Last updated