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
To fix this name conflict we can use namespace
How To Use Namespace
TL;DR
Create a folder structure that match the namespace. Let's use the user example
| |-Mysql |--User.php |-Sqlite |--User.php |-index.php
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: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:
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