Hace poco he estado ayudando a un amigo a entender un código y a modificarlo para que funcione bien con llamadas asíncronas al backend. Un extra sería poder escribirlo de una forma más modular y reutilizable.

El código es un plugin de WordPress escrito con un enfoque muy legacy: una mezcla de lógica de negocio y de frontend en un solo lugar. Manipulaciones de datos hechas en medio del código de la plantilla y cosas por el estilo.

Básicamente, lo que se veía en los sitios PHP a principios de los 2000, antes de todas esas estupendas incorporaciones de programación orientada a objetos al lenguaje y de un montón de frameworks maduros.

El caso en el que estuve trabajando hoy era el siguiente: tienes una tabla que muestra un montón de entradas. Necesitábamos añadir varios filtros a la tabla y hacer que funcionara vía AJAX para refrescar rápidamente la interfaz, sin recargar toda la página de administración de WordPress.

Filtrar los datos fue fácil: un array_filter rápido en línea para filtrar los datos antes de pasarlos al código de la plantilla (para mantener el mismo estilo de código, esto también estaba en el archivo de la plantilla 😇).

El problema llegó cuando empezamos a trabajar en hacer que la tabla pudiera renderizarse mediante AJAX.

Está en medio de un montón de otro código de plantilla y de negocio. Si queríamos limitar la salida vía AJAX solo a la tabla, teníamos pocas formas de lograrlo.

La primera sería envolver el HTML anterior y posterior a la tabla en ENORMES sentencias if para asegurarnos de que no se renderice.

Otra sería extraer la plantilla a un archivo aparte e incluirlo en la acción AJAX que definiríamos en el código del plugin.

¡Las funciones anónimas al rescate!

Pensando en cómo resolver esto de la manera más sencilla posible, intenté definir una función normal de PHP que contuviera el código de la tabla, pero había un problema.

El código se ejecuta dentro de un método de una clase. Hay referencias a $this en la plantilla de la tabla. Si no queremos cambiar demasiado el código, tendríamos que pasar $this como argumento de la función. Pues bien, eso no funciona, porque no se puede pasar $this como parámetro 🤷‍♂️.

Me decepcionó un poco pensar que tendríamos que reescribir un montón de cosas en la plantilla, y había bastantes referencias que queríamos tener en cuenta para que todo siguiera funcionando.

Entonces recordé que el sitio no corre en PHP 5.2, sino en PHP 7, así que las funciones anónimas estarían soportadas.

Y tienen una característica muy útil: puedes definir qué variables del ámbito que hace la llamada se pasarán a la función cuando esta se invoque. Por ejemplo:

$table_function = function() use ( $pages, $current_page, $items ) {
    // ... Table render code
}

Esto te permite hacer referencia directamente a $pages o $items en el cuerpo de la función.

¡Lo genial es que también puedes pasar $this como una variable en el ámbito de la función!

¡Así pudimos extraer por completo el código de renderizado de la tabla a una función separada que podemos llamar de forma aislada durante la llamada AJAX!

Por supuesto, hay que tener mucho cuidado con las variables usadas dentro del cuerpo de la función, ya que tienen que estar definidas, así que hay que fijarse bien desde dónde se puede llamar a la función AJAX.

En nuestro caso, esto significará que añadiremos una pequeña acción en la clase principal que seguirá haciendo el require del archivo, pero tendremos más control para desactivar todas las demás salidas que se producirían.