Beginner Guide to PHP Namespace

Background

When I started using PHP (back when when I use it, it was PHP 7), there was a peculiar feature called namespace. Usually it's used this way

<?php
namespace App\Http\Controller;

use Carbon\Carbon;

class PostController {
    // some code...
}

I was confused. Isn't require and import a thing? It get even more confusing after I use framework like Laravel. I never used import and require ever in Laravel codebase. And then there's composer; a tool that utilize it frequently

So today, I would like to help you write and use namespace in PHP. Let's go!

Why Use Namespace, User Class Example

Let's say you want to fetch user data from database, the one data is in MySQL and the other is in SQLite, so, you write a class that get that data in separate file

<?php
// user_mysql.php

class User {
    private $conn;
    public function __construct($conn) 
    {
        $this->conn = $conn;
    }

    public function getUsers() 
    {
        $stmt = $this->conn->prepare("SELECT * FROM users");
        $stmt->execute();
        $res = $stmt->fetchAll(PDO::FETCH_ASSOC);
        return $res;
    }
}
<?php
// user_sqlite.php

class User {
    private $conn;
    public function __construct($conn) 
    {
        $this->conn = $conn;
    }

    public function getUsers()
    {
        $stmt = $this->conn->prepare("SELECT * FROM users");
        $stmt->execute();
        $res = $stmt->fetchAll(PDO::FETCH_ASSOC);
        return $res;
    }
}

after that you want to display the result, so you import both of the file in there

<?php
// index.php

require('user_mysql.php');
require('user_sqlite.php');

$connMysql = /* mysql pdo object */
$connSqlite = /* sqlite pdo object */

$userMysql = new User($connMysql); // error
$userSqlite = new User($connSqlite) // error

// custom defined function, don't worry about it...
print_as_table($userMysql->getUsers());
print_as_table($userSqlite->getUsers());
?>

however, because the User class is defined in both user_mysql.php and user_sqlite.php it will cause an error like this

Error caused by duplicate User class

To fix this name conflict we can use namespace

How To Use Namespace

TL;DR

  1. Create a folder structure that match the namespace. Let's use the user example

     |
     |-Mysql
     |--User.php
     |-Sqlite
     |--User.php
     |-index.php
    
  2. Add namespace definition in the User file

     <?php
     // Mysql/User.php
     namespace Mysql; // the namespace should match the name of the folder containing the file
    
     class User {
         private $conn;
         public function __construct($conn) 
         {
             $this->conn = $conn;
         }
    
         public function getUsers() 
         {
             $stmt = $this->conn->prepare("SELECT * FROM users");
             $stmt->execute();
             $res = $stmt->fetchAll(\PDO::FETCH_ASSOC);
             return $res;
         }
     }
    
     <?php
     // Sqlite/User.php
     namespace Sqlite;
    
     class User {
         private $conn;
         public function __construct($conn) 
         {
             $this->conn = $conn;
         }
    
         public function getUsers() 
         {
             $stmt = $this->conn->prepare("SELECT * FROM users");
             $stmt->execute();
             $res = $stmt->fetchAll(\PDO::FETCH_ASSOC);
             return $res;
         }
     }
    

    you may also use the use keyword for aliasing like:

  3. import the file in index.php

     <?php
     // index.php
     require('Mysql/User.php');
     require('Sqlite/User.php');
    
     $connMysql = /* mysql pdo object */
     $connSqlite = /* sqlite pdo object */
    
     $userMysql = new Mysql\User($connMysql); // using namespace
     $userSqlite = new Sqlite\User($connSqlite); // using namespace
    
     $resultMysql = $userMysql->getUsers();
     $resultSqlite = $userSqlite->getUsers();
    
     print_as_table($userMysql->getUsers());
     print_as_table($userSqlite->getUsers());
     ?>
    

    you may also use the use keyword to shorten the call. Although for this case, it will lead to naming conflict

A bit more context

Even though I said that you need to create a folder, it will work just fine if you don't create that kind of folder structure, here's a rather ridiculous example

<?php
// user_mysql.php
namespace Pa\Pa\Pi;

class User {
    private $conn;
    public function __construct($conn) 
    {
        $this->conn = $conn;
    }

    public function getUsers() 
    {
        $stmt = $this->conn->prepare("SELECT * FROM users");
        $stmt->execute();
        $res = $stmt->fetchAll(\PDO::FETCH_ASSOC);
        return $res;
    }
}
<?php
// user_sqlite.php
namespace Pu\Po;

class User {
    private $conn;
    public function __construct($conn) 
    {
        $this->conn = $conn;
    }

    public function getUsers() 
    {
        $stmt = $this->conn->prepare("SELECT * FROM users");
        $stmt->execute();
        $res = $stmt->fetchAll(\PDO::FETCH_ASSOC);
        return $res;
    }
}
<?php
// index.php
require('user_sqlite.php');
require('user_mysql.php');

$connMysql = /* mysql pdo object */
$connSqlite = /* sqlite pdo object */

$userMysql = new Pa\Pa\Pi\User($connMysql); // will work just fine
$userSqlite = new Pu\Po\User($connSqlite); // will work just fine

$resultMysql = $userMysql->getUsers();
$resultSqlite = $userSqlite->getUsers();

print_as_table($userMysql->getUsers());
print_as_table($userSqlite->getUsers());
?>

so, why did I suggest to create folder and use namespace that match folder name?

PHP FIG, PSR-4, Composer, Autoloader

There's this group called PHP FIG (PHP Framework Interoperability Group). They consist of PHP projects representative that talk about the commonality of their project so that they find commonality between their project and work together (by project, it could be: framework, PHP based product like Content Management System, library, etc). They then produce a suggestion that each of this project can followed called PSR (PHP Standard Recommendation). There are 20 of accepted standard (in 2024 when this article is written, the number might change in the future). But let's focus on PSR-4.

PSR-4 set standard for autoloading, which basically mean a function that import PHP files, so you don't need to write a bunch of require or import. The folder structure that matched the namespace adhere to PSR-4. And this standard is used by composer for naming package that you can install from packagist, Composer package repository.

Closing Word

So, that's it. To be fair the the section about PHP-FIG, PSR-4, Composer, and Autoloader is a bit unsatisfying, because each of said topic could become it's own article. But I wish this article help you to be able to use namespace. I'll add references below if you want to learn more about it:

References

Namespaces:

Composer:

PHP FIG:
PSR:
0
Subscribe to my newsletter

Read articles from Alexander Septian Arfeprakosa directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Alexander Septian Arfeprakosa
Alexander Septian Arfeprakosa