Namespaces en PHP: declarar, importar con use y evitar colisiones de nombres

Los namespaces en PHP resuelven el problema de las colisiones de nombres cuando se combinan múltiples librerías o cuando el propio proyecto crece y distintos módulos definen clases con el mismo nombre. Introducidos en PHP 5.3, permiten agrupar clases, interfaces, funciones y constantes bajo un prefijo jerarquizado, de modo similar a los directorios en el sistema de ficheros.

Declarar un namespace

La declaración namespace debe ser la primera instrucción del fichero, antes de cualquier código salvo declare(strict_types=1). Un fichero solo puede pertenecer a un namespace, aunque puede tener subespacios anidados.

<?php
declare(strict_types=1);

namespace AppServiciosEmail;

class Mailer
{
    public function enviar(string $destino, string $asunto, string $cuerpo): bool
    {
        // implementación
        return true;
    }
}

// En otro fichero
namespace AppModelos;

class Usuario
{
    public function __construct(
        public readonly int    $id,
        public readonly string $nombre,
        public readonly string $email,
    ) {}
}
?>

Importar clases con use

La instrucción use importa un nombre completo en el espacio de nombres actual, permitiendo referenciarlo por su nombre corto sin escribir el namespace completo en cada uso.

<?php
declare(strict_types=1);

namespace AppControladores;

use AppModelosUsuario;
use AppServiciosEmailMailer;
use AppRepositoriosUsuarioRepositorio;

class RegistroControlador
{
    public function __construct(
        private readonly UsuarioRepositorio $repositorio,
        private readonly Mailer             $mailer,
    ) {}

    public function registrar(string $nombre, string $email): Usuario
    {
        $usuario = $this->repositorio->crear($nombre, $email);
        $this->mailer->enviar($email, 'Bienvenida', "Hola, $nombre");
        return $usuario;
    }
}
?>

Alias con as

Cuando dos clases importadas tienen el mismo nombre corto, o cuando el nombre corto resulta ambiguo, se puede crear un alias con as. También es útil para acortar nombres especialmente largos.

<?php
use AppPagosStripeCliente as StripeCliente;
use AppPagosPayPalCliente as PayPalCliente;
use AppInfraestructuraLoggingMonologAdaptador as Logger;

$stripeCliente = new StripeCliente($apiKey);
$paypalCliente = new PayPalCliente($clientId, $secret);
$log           = new Logger('/var/log/app.log');

// use también funciona para funciones y constantes
use function AppUtilidadesformatearPrecio;
use const AppConfigMAX_REINTENTOS;

echo formatearPrecio(19.99); // llama a AppUtilidadesformatearPrecio
echo MAX_REINTENTOS;         // accede a AppConfigMAX_REINTENTOS
?>

Referenciar el namespace global

Las clases y funciones del namespace global (las de PHP o las definidas sin namespace) se referencian con el prefijo cuando se está dentro de un namespace. Sin este prefijo, PHP busca primero en el namespace actual.

<?php
namespace AppUtilidades;

class Procesador
{
    public function procesar(string $texto): string
    {
        // Sin , PHP buscaría AppUtilidadesstrlen primero
        $longitud = strlen($texto);

        // Clases globales también necesitan el prefijo
        $fecha = new DateTime('now');
        $json  = json_encode(['longitud' => $longitud]);

        // O importarlas con use para no escribir  cada vez
        return $json;
    }
}

// Alternativa: importar en la cabecera del fichero
use DateTime;
use function strlen;
use function json_encode;
?>

Namespaces y PSR-4

El estándar PSR-4 define una correspondencia directa entre el namespace de una clase y la ruta de su fichero. Si el namespace raíz App corresponde al directorio src/, entonces AppControladoresRegistroControlador se encontrará en src/Controladores/RegistroControlador.php. Esta convención es la que siguen Composer y la mayoría de frameworks modernos.

<?php
// composer.json (fragmento)
// {
//   "autoload": {
//     "psr-4": {
//       "App\": "src/"
//     }
//   }
// }

// Estructura de directorios resultante:
// src/
//   Controladores/
//     RegistroControlador.php   ? namespace AppControladores;
//   Modelos/
//     Usuario.php               ? namespace AppModelos;
//   Servicios/
//     Email/
//       Mailer.php              ? namespace AppServiciosEmail;

// Con esta configuración, require vendor/autoload.php carga las clases
// automáticamente sin ningún require_once adicional.
?>

La documentación oficial de namespaces en PHP cubre los casos de uso avanzados como namespaces dinámicos, la función __NAMESPACE__, la importación agrupada con llaves y la resolución de nombres en distintos contextos.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP