Como esta pregunta es bastante antigua, supongo que ya has intentado escribir un ORM. No obstante, cuando escribí un ORM personalizado hace dos años, me gustaría compartir mi experiencia e ideas.
Como dije, implementé un ORM personalizado hace dos años e incluso lo utilicé con cierto éxito en proyectos pequeños a medianos. Lo integé en un CMS bastante popular que en ese momento (e incluso ahora) carece de dicha funcionalidad ORM. Además, en aquel entonces, marcos populares como Doctrine realmente no me convencían. Mucho ha cambiado desde entonces y Doctrine 2 evolucionó en un marco sólido, entonces, si ahora tuviera la opción entre implementar mi propio ORM o usar uno de los frameworks populares como Doctrine 2 para uso de producción, esto no sería ninguna duda: use el soluciones existentes y estables. PERO: la implementación de dicho marco (de manera simple) fue un ejercicio de aprendizaje muy valioso y me ayudó mucho al trabajar con ORM de código abierto más grandes, a medida que comprendes mejor las trampas y dificultades asociadas con el mapeo relacional de objetos.
No es demasiado difícil implementar la funcionalidad básica de ORM, pero tan pronto como el mapeo de las relaciones entre objetos entran en juego, se vuelve mucho, mucho más difícil/interesante.
¿Cómo comencé?
Lo que me enganchó fue el libro de Martin Fowlers Patterns of Enterprise Application Architecture. Si desea programar su propio ORM o incluso si solo está trabajando con algún marco ORM, compre este libro. Es uno de los recursos más valiosos que cubren muchas de las técnicas básicas y avanzadas relacionadas con el campo del mapeo relacional de objetos. Lea sobre esto, obtendrá muchas ideas geniales sobre los patrones detrás de un ORM.
Arquitectura Básica
Decidí que si me gustaría utilizar en lugar de un enfoque Active Record o algún tipo de Data Mapper. Esta decisión influye en cómo los datos de la base de datos se asignan a la entidad. Decidí implementar un Data Mapper simple, el mismo enfoque que Doctrine 2 o Hibernate en los usos de Java. Active Record es el enfoque de la funcionalidad ORM (si puede llamarlo así) en Zend Framework. Active Record es mucho más simple que Data Mapper, pero también mucho más limitado. Lea sobre estos patrones y verifique los marcos mencionados, obtiene la diferencia bastante rápido. Si decide ir con un Data Mapper, también debe leer en PHPs reflection API.
Consulta
que tenían el ambicioso objetivo de crear mi propio lenguaje de consulta, al igual que en Doctrina DQL o HQL en Hibernate. Pronto lo abandoné, ya que escribir un analizador/lexer de SQL personalizado parecía complicado (¡y realmente lo es!). Lo que hice fue implementar un Query Object, para encapsular la información que tabla está involucrada en la consulta (eso es importante ya que necesita mapear los datos de la base de datos a las clases relevantes para cada tabla).
Consulta para un objeto en mi ORM se veía así:
public function findCountryByUid($countryUid) {
$queryObject = new QueryObject();
$queryObject->addSelectFields(new SelectFields('countries', '*'))
->addTable(new Table('countries'))
->addWhere('countries.uid = "' . intval($countryUid) . '"');
$res = $this->findByQuery($queryObject);
return $res->getSingleResult();
}
configuración
Normalmente, también es necesario tener algún tipo de formato de configuración, Hibernate utiliza XML (entre otros), Doctrine 2 usa anotaciones PHP, EZComponents usa matrices PHP en su Persistent Object component como formato de configuración. Eso es lo que usé, también, parecía una elección natural y el CMS con el que trabajé también usó el formato de configuración de PHP.
Con esa configuración, se definen
- qué tabla se asigna a qué clase
- qué campos debe quedar asignada a la instancia de clase
- qué tipo los campos de la tabla tienen (int, string , etc.)
- las relaciones entre las entidades (por ejemplo, una clase de usuario tiene una referencia a una clase UserGroup)
- etc.
Y esa es la información que utiliza en su Data Mapper para asignar el resultado de DB a los objetos.
Implementación
yo decidimos ir con un enfoque basado en pruebas fuertes, debido a la naturaleza compleja de escribir un ORM personalizado. TDD o no, escribir muchas, muchas pruebas de unidades es una muy buena idea en un proyecto así. Aparte de eso: ensúciate las manos y mantén el libro de Fowlers cerca. ;-)
Como ya he dicho que era realmente vale la pena el esfuerzo, pero no le gustaría hacerlo de nuevo, tanto a causa de los marcos maduras que existen hoy en día.
Ya no uso mi ORM, funcionó, pero carecía de muchas características, entre otras: carga diferida, asignación de componentes, soporte de transacciones, almacenamiento en caché, tipos personalizados, declaraciones/parámetros preparados, etc. Y su rendimiento no era Es lo suficientemente bueno para usarlo en proyectos a gran escala.
No obstante, espero poder darte algunos puntos de partida en el campo de ORM, si aún no los conocías. ;-)
Gran visión general. Usted tiene un punto válido acerca de la existencia de soluciones probadas, pero de todos modos introdujo algunas ideas importantes que debo tener en cuenta cuando me dedico al diseño de mi propio ORM. Me alegra que fue una gran experiencia de aprendizaje para ti también. Me aseguraré de buscar el libro de Fowler una vez que esté afuera. Si no aparecen nuevas respuestas durante unos días, puede obtener otro +15. ¡Gracias por tu tiempo y explicación! :) – BoltClock