Introducción a Namespaces
Los namespaces son la forma de organizar y agrupar código en PHP. Resuelven el problema de colisiones de nombres cuando usas múltiples librerías o trabajas en proyectos grandes.
El problema sin namespaces
Imagina que estás usando dos librerías
diferentes. Ambas definen una clase llamada
Usuario. Sin namespaces, PHP no
sabría cuál usar:
<?php
// libreria1/Usuario.php
class Usuario
{
public function __construct(
public readonly string $nombre
) {}
}
// libreria2/Usuario.php
class Usuario // ERROR: No se puede redeclarar la clase Usuario
{
public function __construct(
public readonly int $id,
public readonly string $email
) {}
}
Esto genera un error fatal. Los namespaces resuelven este problema creando "espacios" separados para cada grupo de código.
¿Qué es un namespace?
Un namespace es como una carpeta virtual que
agrupa clases, interfaces, funciones y
constantes relacionadas. Piénsalo como los
directorios en tu sistema de archivos: puedes
tener un archivo config.php en
diferentes carpetas sin conflicto.
<?php
// src/Auth/Usuario.php
namespace Auth;
declare(strict_types=1);
class Usuario
{
public function __construct(
public readonly string $nombre,
public readonly string $password
) {}
public function verificarPassword(string $intento): bool
{
return password_verify($intento, $this->password);
}
}
<?php
// src/Blog/Usuario.php
namespace Blog;
declare(strict_types=1);
class Usuario
{
public function __construct(
public readonly int $id,
public readonly string $nombrePublico,
public readonly string $bio
) {}
}
Ahora tenemos dos clases
Usuario que coexisten sin
problemas: Auth\Usuario y
Blog\Usuario.
Declarar un namespace
El namespace se declara al inicio del archivo,
antes de cualquier otro código (excepto
declare):
<?php
namespace MiProyecto\Servicios;
declare(strict_types=1);
class EmailService
{
public function enviar(string $destinatario, string $mensaje): bool
{
// Lógica para enviar email
return true;
}
}
El namespace debe ir
primero (después de
<?php), seguido de
declare(strict_types=1).
Nada más puede ir antes del namespace.
Namespaces anidados
Los namespaces pueden tener múltiples niveles,
separados por \:
<?php
// Estructura típica de proyecto
namespace App\Http\Controllers; // Para controladores
namespace App\Models; // Para modelos
namespace App\Services\Payment; // Para servicios de pago
namespace App\Exceptions; // Para excepciones personalizadas
Usar clases de otros namespaces
Para usar una clase de otro namespace, debes referirte a ella con su nombre completo (Fully Qualified Name o FQN):
<?php
namespace App\Controllers;
declare(strict_types=1);
class UsuarioController
{
public function mostrar(int $id): void
{
// Nombre completo con \ inicial (FQN absoluto)
$usuarioAuth = new \Auth\Usuario('admin', 'hash');
// Nombre completo sin \ inicial (relativo al namespace actual)
$usuarioBlog = new \Blog\Usuario(1, 'Admin', 'Bio del admin');
echo $usuarioAuth->nombre;
echo $usuarioBlog->nombrePublico;
}
}
La \ inicial indica un
nombre absoluto desde la raíz. Sin ella,
PHP busca relativo al namespace actual.
En la siguiente lección veremos
use para evitar escribir
nombres tan largos.
El namespace global
Las clases nativas de PHP (como
DateTime, Exception)
viven en el namespace global. Desde dentro de un
namespace, debes usar \ para
acceder a ellas:
<?php
namespace App\Servicios;
declare(strict_types=1);
class Logger
{
public function log(string $mensaje): void
{
// DateTime es una clase global, necesita \
$fecha = new \DateTime();
// Exception también es global
if ($mensaje === '') {
throw new \InvalidArgumentException('El mensaje no puede estar vacío');
}
echo "[{$fecha->format('Y-m-d H:i:s')}] $mensaje\n";
}
}
Funciones y constantes globales
Las funciones y constantes nativas de PHP se buscan primero en el namespace actual, y si no se encuentran, en el global:
<?php
namespace App\Utils;
declare(strict_types=1);
class StringHelper
{
public function procesar(string $texto): string
{
// strlen() se busca en App\Utils primero, luego en global
// Funciona sin \ porque no hay strlen() en este namespace
$longitud = strlen($texto);
// Para ser explícito, puedes usar \
$mayusculas = \strtoupper($texto);
// Constantes como PHP_EOL también funcionan
return $mayusculas . PHP_EOL;
}
}
Definir funciones y constantes en namespaces
No solo clases, también puedes definir funciones y constantes dentro de un namespace:
<?php
namespace App\Helpers;
declare(strict_types=1);
// Constante en el namespace
const VERSION = '1.0.0';
// Función en el namespace
function formatearPrecio(float $precio): string
{
return number_format($precio, 2, ',', '.') . ' €';
}
// Uso desde otro archivo:
// echo \App\Helpers\VERSION;
// echo \App\Helpers\formatearPrecio(1234.56);
Ejemplo práctico: Estructura de una aplicación
<?php
// src/Models/Producto.php
namespace App\Models;
declare(strict_types=1);
class Producto
{
public function __construct(
public readonly int $id,
public readonly string $nombre,
public readonly float $precio
) {}
}
<?php
// src/Services/CarritoService.php
namespace App\Services;
declare(strict_types=1);
class CarritoService
{
/** @var \App\Models\Producto[] */
private array $productos = [];
public function agregar(\App\Models\Producto $producto): void
{
$this->productos[] = $producto;
}
public function calcularTotal(): float
{
$total = 0.0;
foreach ($this->productos as $producto) {
$total += $producto->precio;
}
return $total;
}
public function vaciar(): void
{
$this->productos = [];
}
}
<?php
// index.php
declare(strict_types=1);
require_once 'src/Models/Producto.php';
require_once 'src/Services/CarritoService.php';
// Usar nombres completos
$producto = new \App\Models\Producto(1, 'Laptop', 999.99);
$carrito = new \App\Services\CarritoService();
$carrito->agregar($producto);
echo "Total: " . $carrito->calcularTotal(); // Total: 999.99
Ejercicios
Ejercicio 1: Namespaces básicos
Crea dos clases
Validador: una en el
namespace
App\Validators\Email con un
método
validar(string $email): bool
que valide emails, y otra en
App\Validators\Password con
un método que valide que la contraseña
tenga al menos 8 caracteres.
Ver solución
<?php
// src/Validators/Email/Validador.php
namespace App\Validators\Email;
declare(strict_types=1);
class Validador
{
public function validar(string $email): bool
{
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
}
// src/Validators/Password/Validador.php
namespace App\Validators\Password;
declare(strict_types=1);
class Validador
{
public function validar(string $password): bool
{
return strlen($password) >= 8;
}
}
// Uso
$emailValidator = new \App\Validators\Email\Validador();
$passValidator = new \App\Validators\Password\Validador();
var_dump($emailValidator->validar('test@example.com')); // true
var_dump($passValidator->validar('12345678')); // true
Ejercicio 2: Usando clases globales
En el namespace
App\Logs, crea una clase
FileLogger que tenga un
método
log(string $mensaje): void
que use \DateTime para
añadir la fecha al mensaje. Si el
mensaje está vacío, debe lanzar una
\InvalidArgumentException.
Ver solución
<?php
// src/Logs/FileLogger.php
namespace App\Logs;
declare(strict_types=1);
class FileLogger
{
public function log(string $mensaje): void
{
if ($mensaje === '') {
throw new \InvalidArgumentException(
'El mensaje no puede estar vacío'
);
}
$fecha = new \DateTime();
$linea = sprintf(
'[%s] %s',
$fecha->format('Y-m-d H:i:s'),
$mensaje
);
echo $linea . PHP_EOL;
}
}
// Uso
$logger = new \App\Logs\FileLogger();
$logger->log('Usuario conectado');
// [2024-01-15 10:30:45] Usuario conectado
Ejercicio 3: Funciones en namespaces
Crea un archivo con el namespace
App\Utils\Arrays que
contenga una función
aplanar(array $array): array
que convierta un array multidimensional
en uno simple. Demuestra cómo llamarla
desde otro namespace usando el nombre
completo.
Ver solución
<?php
// src/Utils/Arrays.php
namespace App\Utils\Arrays;
declare(strict_types=1);
function aplanar(array $array): array
{
$resultado = [];
foreach ($array as $elemento) {
if (is_array($elemento)) {
$resultado = array_merge($resultado, aplanar($elemento));
} else {
$resultado[] = $elemento;
}
}
return $resultado;
}
// Desde otro namespace
namespace App\Controllers;
$datos = [[1, 2], [3, [4, 5]], 6];
$plano = \App\Utils\Arrays\aplanar($datos);
print_r($plano);
// [1, 2, 3, 4, 5, 6]
¿Has encontrado un error o tienes sugerencias para esta lección?
Enviar feedback¿Te está gustando el curso?
Tenemos cursos premium con proyectos reales y soporte.
Descubrir cursos premium