Creando clases y objetos flexibles de forma dinámica con eval y ArrayObject en PHP

Debo reconocer que hasta ahora no me había pasado tener la necesidad inevitable y “real” de crear clases “on the fly” (clases al vuelo) hasta que el objeto colector de Europio Engine me enfrentó a ello.

Les explico el problema para que puedan entender cuál fue la motivación para crear este tipo de clases:
Europio Engine, cuenta con objetos genéricos necesarios en cualquier aplicación. Entre ellos, CollectorObject: un objeto colector.

Como explico en el capítulo XVII de mi libro sobre Teoría de Objetos, el objeto colector para un tipo dado, debe ser un Singleton, es decir un objeto de instancia única, pues solo podrá existir una -y solo una- colección para un mismo objeto.

En Europio Engine CollectorObject es un colector genérico. Llamando a CollectorObject::get('NombreDelObjeto') se puede obtener toda la colección de objetos NombreDelObjeto persistentes en el sistema a través de CollectorObject::$collection.

Sin embargo, al ser un objeto de instancia única, si la colección no era recuperada ANTES de solicitar una nueva colección, la última llamada sobrescribía a la primera.

Es entonces que no solo a nivel práctico se hacía necesario poder crear “on the fly” un NombreDelObjetoCollection sino además, ¡a nivel conceptual! Pues un colector genérico, no puede ser de instancia única. Pero, si dejaba de ser de instancia única, dejaba de ser un colector. Así nació la necesidad de crear una clase al vuelo y después de mucho investigar, descubrí que la única forma de hacerlo “sin rodeos ni códigos raros”, era utilizando eval().

Con una simple línea como esta que sigue, quedaba todo resuelto:

Lo anterior, creará al vuelo la clase ProductoCollection produciendo el siguiente código:

Que al heredar de CollectorObject generaría un Singleton Colector sin más rodeos. Y a raíz de esto, comencé a pensar en la Standard PHP Library (SPL) y su tan discutido ArrayObject.

Para quiénes no estén del todo al tanto, ArrayObject es una clase de PHP que permite tratar a un array como si fuese un objeto (sé que es discutible pero no viene al caso ya que solo se trata de experimentar). Para que se entienda mejor, lo mostraré directamente con el código:

Lo anterior producirá:

Otro ejemplo, pero esta vez, creando un objeto desde un array asociativo:

Como pueden ver, la clase ArrayObject no es para nada compleja de entender e incorporándola a eval(), me podría dar la posibilidad de crear clases al vuelo y prácticamente anónimas, produciendo objetos de diversos tipos. ¿Cómo? Creando una simple clase “estática” que se encargue de todo:

De esta forma, crear una clase al vuelo, podría hacerse de dos formas:

Y por supuesto, vale aclarar que en cualquiera de los dos casos, tanto la llamada a Object::set('ClassName'); como la instancia al nuevo objeto $obj = new ClassName(); podrán recibir como parámetro, un array asociativo que emule las propiedades del nuevo objeto.

¡Espero que disfruten del experimento!

 

eugeniabahit