2009-12-28 27 views
8

Tengo una tabla llamada Cat, y una clase PHP llamada Cat. Ahora quiero hacer una clase CatDataMapper, de modo que Cat extends CatDataMapper.¿Cómo se ve un Data Mapper?

Quiero que la clase Data Mapper proporcione la funcionalidad básica para hacer ORM, y para crear, editar y eliminar Cat.

Para ese propósito, ¿tal vez alguien que conozca este patrón muy bien podría darme algún consejo útil? Siento que sería un poco demasiado simple solo proporcionar algunas funciones como update(), delete(), save().

Me doy cuenta de que un Data Mapper tiene este problema: Primero crea la instancia de Cat, luego inicializa todas las variables como name, furColor, eyeColor, purrSound, meowSound, asistentes, etc. y después de que todo esté configurado, usted llama a la función save() heredada de CatDataMapper. Esto fue simple;) Pero ahora, el problema real: consulta la base de datos de gatos y obtiene un conjunto de resultados aburridos con muchos datos de gatos.

PDO cuenta con algunas capacidades ORM para crear instancias Cat. Digamos que lo uso, o incluso digo que tengo una función mapDataset() que toma una matriz asociativa. Sin embargo, tan pronto como obtuve mi objeto Cat de un conjunto de datos, tengo datos redundantes. Al mismo tiempo, veinte usuarios podían recoger los mismos datos de gato de la base de datos y editar el objeto cat, es decir, cambiar el nombre del gato y guardarlo(), mientras que otro usuario todavía tiene que ver con establecer otro furColor. Cuando todos ellos guardan sus ediciones, todo está en mal estado.

Err ... ok, para mantener esta pregunta realmente corta: ¿Qué es una buena práctica aquí?

Respuesta

12

De DataMapper in PoEA

El asignador de datos es una capa de software que separa los objetos en memoria de la base de datos.Su responsabilidad es transferir datos entre los dos y también para aislarlos de cada uno . Con Data Mapper, los objetos en memoria no necesitan saber siquiera que hay una base de datos presente en ; no necesitan el código de interfaz SQL , y ciertamente no hay conocimiento de del esquema de la base de datos. (El esquema de base de datos es siempre ignorante de los objetos que lo usan.) Dado que es un formulario de Mapper (473), Data Mapper es incluso desconocido para el dominio capa.

Por lo tanto, un gato no debe extender CatDataMapper porque eso crearía una relación is-a y uniría el nivel Cat a la capa de persistencia. Si desea ser capaz de manejar la persistencia de sus Gatos de esta manera, mire en ActiveRecord o cualquiera de los otros Patrones arquitectónicos de origen de datos.

Generalmente utiliza un DataMapper cuando usa un Modelo de dominio. Un DataMapper simple simplemente correlacionaría una tabla de base de datos con una clase en memoria equivalente campo por campo. Sin embargo, cuando surge la necesidad de un DataMapper, por lo general no tendrá relaciones tan simples. Las tablas no asignarán 1: 1 a sus objetos. En cambio, se podrían formar múltiples tablas en un Object Aggregate y viceversa. En consecuencia, la implementación de solo métodos CRUD, puede convertirse en todo un desafío.

Aparte de eso, es uno de los patrones más complicados (cubre 15 páginas en PoEA), a menudo se utiliza en combinación con el Repository pattern entre otros. Mire en la columna de preguntas relacionadas en el lado derecho de esta página para preguntas similares.

En cuanto a su pregunta sobre varios usuarios que editan el mismo gato, ese es un problema común llamado Concurrency. Una solución para eso sería locking the row, mientras que alguien lo edita. Pero como todo, esto puede lead to other issues.

+0

Tengo una pregunta con respecto a Data mapper vs Table Data gateway (TDG). Las tablas de patrones TDG mapean 1: 1 con una tabla, pero a menudo en algunos métodos de clase TDG, necesitamos unirnos a la tabla principal con otras tablas (para unirnos a algunas tablas padre para seleccionar información adicional). ¿Eso viola el patrón de puerta de enlace de datos de tabla? En mi humilde opinión, tan pronto como agregue otras tablas de DB (incluso combinaciones) en sentencias de SQL en métodos de clase TDG, o divida su modelo (modelo de dominio o datos de tabla) en dos clases - la clase se convierte en una clase de mapeador de datos. IMHO Data Mapper es solo una evolución normal de sus clases de TDG. – Centurion

+0

Además, si su clase de fuente de datos implementada es capaz de conectarse a varias fuentes (DB o algún servicio web), en mi humilde opinión, ha implementado la clase de mapeador de datos. – Centurion

+0

Fowler afirma en POEAA que un TDG puede contener el código para acceder a muchas tablas/vistas, así que supongo que también puede hacer uniones en él. Pero, por supuesto, eso significa que los resultados devueltos ya no coincidirán con 1: 1 en las tablas y que necesitará actualizaciones especializadas e Insertar consultas para esas filas, además de las genéricas. Puedo ver cómo eso te hace concluir que se parece a Data Mapper, pero el propósito de Data Mapper es mucho más complejo que eso. No es solo JOIN => DataMapper. Eche un vistazo a http://css.dzone.com/books/practical-php-patterns/practical-php-patterns-data – Gordon

0

Mantenga la respuesta corta: Tiene una instancia de Cat. (Tal vez se extiende CatDbMapper o Cat3rdpartycatstoreMapper) Usted llama:

$cats = $cat_model->getBlueEyedCats(); 
//then you get an array of Cat objects, in the $cats array 

no sabe lo que usted utiliza, es posible echar un vistazo a algún marco php para la mejor comprensión.

+0

Creo que describió ActiveRecord, no DataMapper. –

2

Si depende de ORM como Doctrine o Propel, el principio básico es crear una clase estática que obtener los datos reales de la base de datos, (por ejemplo Propel crearía CatPeer), y los resultados recuperados por la clase Peer luego sería "hidratado" en objetos Cat.

El proceso de hidratación es el proceso de convertir un conjunto de resultados MySQL "aburrido simple" en objetos agradables que tienen getters y setters.

Por lo tanto, para recuperar, usaría algo como CatPeer::doSelect(). Entonces, para un nuevo objeto que le primera instanciarlo (o recuperar e instancia de la BD): $cat = new Cat();

La inserción podría ser tan simple como hacer: $cat->save(); Eso sería equivalente a una inserción (o una actualización si el objeto ya existe en el db ... El ORM debe saber cómo hacer la diferencia entre objetos nuevos y existentes utilizando, por ejemplo, la presencia ort ausencia de una clave primaria).

1

PDO cuenta con algunas capacidades ORM para crear instancias de Cat. Digamos que uso que, o incluso digamos que tengo una función mapDataset() que toma una matriz asociativa . Sin embargo, tan pronto como obtuve mi objeto Cat de un conjunto de datos, I tiene datos redundantes. Al mismo tiempo, veinte usuarios podrían recoger los mismos datos de gato de la base de datos y editar el objeto gato, es decir, cambiar el nombre del gato, y guardar(), mientras que otro usuario todavía cosas acerca de la configuración otra furColor. Cuando todos ellos guardan sus ediciones , todo está en mal estado.

Con el fin de hacer un seguimiento del estado de los datos y normalmente IdentityMap y/o una UnitOfWork se utilizarían no perder de vista todos los teh diferentes operaciones sobre entidades mapeadas ... y al final del ciclo de petición al las operaciones entonces se realizaría.

2

Implementar un Data Mapper es muy difícil en PHP < 5.3, ya que no puede leer/escribir campos protegidos/privados.Usted tiene algunas opciones a la hora de cargar y guardar los objetos:

  1. utilizan algún tipo de solución, como la serialización del objeto, modificando su representación de cadena, y llevarlo de vuelta con unserialize
  2. Hacer todos los campos públicos
  3. Manténgalos protegida privada /, y escribir mutators/descriptores de acceso para cada uno de ellos

el primer método tiene la posibilidad de romper con una nueva versión, y es truco muy cruda, el segundo se considera una (muy) mala práctica.

La tercera opción también se considera mala práctica, ya que no debe proporcionar getters/setters para todos sus campos, solo los que lo necesitan. Su modelo se "daña" desde una perspectiva pura de DDD (diseño impulsado por el dominio), ya que contiene métodos que solo son necesarios debido al mecanismo de persistencia. También significa que ahora debe describir otra asignación para los campos -> métodos setter, al lado de los campos -> columnas de la tabla.

PHP 5.3 introduce la posibilidad de acceder/cambiar todo tipo de campos, mediante el uso de la reflexión:

http://hu2.php.net/manual/en/reflectionproperty.setaccessible.php

Con esto, se puede lograr una verdadera asignador de datos, debido a la necesidad de proporcionar mutadores para todos de los campos ha cesado.

Cuestiones relacionadas