TruquiTrucos Dev – Qué son los namespaces de PHP

Publicada en WordPress.

Hace aproximadamente un año ya que WordPress decidió dejar atrás la compatibilidad con la versión 5.2 de PHP, que había estado usando desde el 2010, y exigir versiones más modernas. De hecho, a día de hoy la versión mínima de PHP recomendada por WordPress es una de las más recientes: PHP 7.3.

Si eres un simple usuario de WordPress, esto probablemente no te impacte demasiado (más allá de que estas nuevas versions dan un mejor rendimiento).

Pero si eres un desarrollador, las nuevas versiones de PHP traen novedades… novedades que, por fin, puedes usar en tus plugins y temas con la certeza de que funcionarán en todos tus usuarios. Y hoy, en concreto, me gustaría hablarte de una que lleva ya muchísimo tiempo entre nosotros pero que, quizás, no conocías: los namespaces, o espacios de nombres.

WordPress y los «prefijos» en nuestro código

Una de las primeras normas que aprendes como desarrollador WordPress es la de «usar prefijos en todo lo que hacemos» para evitar «colisiones de nombres». Tal y como podemos leer en las mejores prácticas de WordPress:

Las colisiones de nombres ocurren cuando tu plugin usa un nombre para una variable, función o clase que ya está usando otro plugin.

Para evitarlas, tienes que prefijar todos los nombres con una cadena de texto única. Así, consigues evitar que otros plugins usen accidentalmente variables o funciones de tu código, así como que tú uses las de otros.

Mejores prácticas para el desarrollo de plugins en WordPress

Así, por ejemplo, aprendemos que en lugar de crear una función como get_site_id, es mejor usar una como nelio_content_get_site_id. De esta forma, somos capaces de identificar rápidamente el plugin (o tema) (nelio_content) al que pertenece una cierta función (get_site_id) y nos ahorramos errores fatales si varios plugins intentan definir la misma función.

Usar prefijos es una forma rudimentaria de crear un «espacio de nombres»; un apaño que teníamos que hacer cuando no había nada mejor. Todos aquellos elementos que usen el mismo prefijo forman parte del mismo conjunto o namespace. Pero claro, a cambio tenemos un código innecesariamente más complejo: los nombres son más largos por culpa de prefijos que no aportan nada.

Namespaces en PHP

La versión 5.3 de PHP introdujo el concepto de namespace. La definición que dan del mismo en la documentación me parece excelente, así que te la reproduzco aquí:

Los espacios de nombres son una manera de encapsular elementos. Se pueden ver como un concepto abstracto en muchos aspectos. Por ejemplo, en cualquier sistema operativo, los directorios sirven para agrupar ficheros relacionados, actuando así como espacios de nombres para los ficheros que contienen. Como ejemplo, el fichero foo.txt puede existir en los directorios /home/greg y /home/otro, pero no pueden coexistir dos copias de foo.txt en el mismo directorio.

En el mundo de PHP, los espacios de nombres están diseñados para solucionar dos problemas con los que se encuentran los autores de bibliotecas y de aplicaciones al crear elementos de código reusable, tales como clases o funciones:

1. El conflicto de nombres entre el código que se crea y el que existe internamente en PHP o en bibliotecas de terceros.

2. La capacidad de abreviar Nombres_Extra_Largos, mejorando la legibilidad del código fuente.

Documentación de PHP

Cómo crear un namespace

La creación de un namespace en PHP es de lo más sencillo que hay. Sencillamente, al principio del fichero PHP que crees, añade una directiva namespace con el nombre que quieras usar y «todo» lo que definas en ese fichero pertenecerá a ese namespace:

<?php
namespace Nelio_Content;

Con esta sencilla línea, «todo» lo que metamos a continuación estará dentro del namespace Nelio_Content. Por ejemplo, si defino una función como la que comentaba al principio:

<?php
namespace Nelio_Content;

function get_site_id() {
  // ...
}

ahora sabemos que get_site_id está dentro del namespace Nelio_Content. De esta forma, ya no tenemos que usar el prefijo nelio_content_ en el momento de definir la función. ¡Genial!

Excepciones a los namespaces

Si te fijas atentamente a lo que te he contado hasta ahora, verás que he estado escribiendo «todo» entre comillas: «»todo» lo que metamos estará dentro del namespace». ¿Por qué? Porque en realidad los namespaces no funcionan con absolutamente todo el código que escribamos.

Los namespaces de PHP únicamente cubren los siguientes elementos PHP:

  • Clases
  • Interficies
  • Traits
  • Funciones
  • Constantes declaradas con const pero no con define

Además, hay algunas cosas adicionales en WordPress que también necesitamos que estén en su propio espacio de nombres y que, por desgracia, los namespaces de PHP no cubren: los handles de tus scripts, opciones de la base de datos o los tipos de contenido personalizados y sus meta datos, etc. En todos estos casos, deberás seguir usando prefijos.

Cómo importar elementos de un namespace a otro

Si necesitas usar un elemento que está en tu mismo namespace, no tienes que hacer absolutamente nada especial: simplemente llámalo por su nombre. Por ejemplo, en el siguiente fragmento de código:

<?php
namespace Nelio_Content;

function get_site_id() {
  // ...
}

function get_auth_token() {
  $site_id = get_site_id();
  // ...
}

puedes ver que hemos definido dos funciones: get_site_id y get_auth_token, ambas dentro del espacio de nombres Nelio_Content. Cuando la función get_auth_token necesita usar get_site_id, la llama directamente por su nombre y listo.

Si, por otro lado, necesitas usar la función get_site_id en un namespace diferente, debes llamar la función usando su identificador completo:

<?php
namespace Something_Else;

function do_some_action() {
  $site_id = Nelio_Content\get_site_id();
  // ...
}

o bien debes importar la función con la palabra clave use:

<?php
namespace Something_Else;

use Nelio_Content\get_site_id;

function do_some_action() {
  $site_id = get_site_id();
  // ...
}

A mí personalmente me gusta mucho la segunda opción: usando el keyword use para importar funciones de otros namespaces, porque echando un vistazo rápido a la cabecera de tu fichero puedes identificar las dependencias del mismo.

Filtros y acciones de WordPress junto a namespaces de PHP

Hay un detalle importante que debes tener en cuenta a la hora de usar namespaces junto a los filtros y acciones de WordPress. Cuando especificas la función que hay que llamar cuando se ejecuta un filtro o una acción, muchas veces lo haces usando una cadena de texto:

<?php
// ...
add_action( 'init', 'do_some_action' );

El problema es que si dicha función está dentro de un namespace, el hook anterior no te funcionará. Para que funcione debidamente, debes indicarle a WordPress dónde está exactamente dicha función, así que siempre, siempre, siempre debes especificar su nombre completo.

¿Estás añadiendo el hook en el fichero donde defines el propio namespace? Da igual, pon el nombre completo:

<?php
namespace Nelio_Content;

function do_some_action() {
 // ...
}
add_action( 'init', 'Nelio_Content\do_some_action' );

¿Estás en otro namespace pero has hecho un import con use? Da igual también, pon el nombre completo:

<?php
namespace Something_Else;

use Nelio_Content\do_some_action;
// ...

add_action( 'init', 'Nelio_Content\do_some_action' );

Usando alias junto a nuestros namespaces

Otra funcionalidad muy interesante de los namespaces es que nos permiten cambiar el nombre de sus elementos en el momento en el que vamos a usarlos en otro namespace. Por ejemplo, imagina que tenemos esto:

<?php
namespace Nelio_Content;

function get_site_id() {
  // ...
}

Si quiero usar esta función en otro namespace, ya hemos visto que puedo hacerlo con use. Pero claro, lo mismo no me interesa que la función en este otro módulo se siga llamando get_site_id, porque quizás es confuso o quizás incluso quiero definir yo mismo una función get_site_id en mi módulo. En este caso, lo más sencillo es usar un alias:

<?php
namespace Something_Else;

use Nelio_Content\get_site_id as get_nc_site_id();

function get_site_id() {
  // ...
}

function do_some_action() {
  $nc_site_idd = get_nc_site_id();
  // ...
}

¡Empieza a usar namespaces hoy mismo!

Los namespaces son una herramienta fantástica para evitar las colisiones de nombres y para organizar nuestro código. De hecho, y aunque no lo he comentado en esta entrada, existen estándares como PSR-4 para que PHP sea capaz de cargar clases automáticamente gracias a que la estructura de namespaces que usas y cómo organizas el código en directorios y ficheros coincide.

Si aún no estás usando namespaces en tus proyectos, te recomendamos que empieces a hacerlo de ahora en adelante. En seguida verás que tu código queda más ordenado y limpio. ¡Cuéntanos tu experiencia en los comentarios!

Imagen destacada de Chaitanya Tvs en Unsplash.

Deja un comentario

No publicaremos tu correo electrónico. Los campos obligatorios están marcados con: •

He leído y acepto la Política de privacidad de Nelio Software

Al marcar la casilla de aceptación estás dando tu legítimo consentimiento para que tu información personal se almacene en SiteGround y sea usada por Nelio Software con el propósito único de publicar aquí este comentario. Contáctanos para corregir, limitar, eliminar o acceder a tu información.