php database design-patterns zend-framework zend-db-table

php - Zend framework-¿Por qué debería usar data mapper/Db_Table_Row?



database design-patterns (2)

Pregunta extendida: ¿Por qué debería usar Data Mapper / Db_Table_Row, mientras que DbTable es capaz de manejar la mayoría de las tareas básicas para la manipulación de datos.

Actualmente estoy aprendiendo ZF v1.11

Para la manipulación de la base de datos, creé DbTable para cada tabla. Por ejemplo, la tabla de "usuarios" está representada por Application_Model_DbTable_Users sin códigos adicionales allí.

Al manipular datos, puedo usar:

<?php $uTable = new Application_Model_DbTable_Users(); $newUid = $uTable->insert(array(''name''=>''Old Name'', ''email''=>'''')); $user = $uTable->find($newUid)->current(); // Then I can use $user which is instance of Table_Row $user->name = "New Name"; $user->email = "[email protected]"; $user->save();

Mi pregunta es, ¿cuándo tendría que definir una clase de fila (suponiendo que Table_Row se conoce como DataMapper en ZF-Tutorials)?

// By, adding this to the DbTable class protected $_rowClass = ''Application_Model_User'';

¿Cuáles son los beneficios de tener una clase Row para cada entidad? ¿Alguien puede señalarme las mejores prácticas para esto?


En pocas palabras: se trata de aislamiento.

Zend_Db_Table es una implementación de Table Data Gateway. Canaliza el acceso de CRUD a una vista de tabla específica a través de una clase. Por lo general, se utiliza con un Módulo de tabla , por ejemplo, una clase que contiene la lógica comercial para los registros manejados por una puerta de enlace.

Zend_Db_Table_Row es una implementación del patrón Row Data Gateway . Aquí, los objetos devueltos se ven exactamente como un registro de base de datos y contienen la lógica de negocio para trabajar con esos datos, pero no contienen la lógica para CRUD con la tabla de la que son (que sería un ActiveRecord) sino que los agregan.

Los gateways de datos de fila están bien siempre que no tenga demasiada discrepancia en la impedancia relacional del objeto . Cómo persiste un objeto en una base de datos relacional y cómo debería verse en un mundo de objetos a menudo son cosas muy diferentes. Al usar un Modelo de Dominio , sus objetos comerciales generalmente están estructurados de una manera diferente a como están almacenados en la base de datos. Por lo tanto, no puede CRUDARlos fácilmente de la base de datos. Aquí es donde DataMapper entra en juego.

Un DataMapper toma la responsabilidad de mapear objetos de dominio en Recordsets y viceversa. Esto hace que su aplicación sea más fácil de mantener porque desacopla sus objetos de dominio de la estructura de la base de datos. Los mantiene separados y le da más flexibilidad sobre cómo modelar ambas capas (persistencia y dominio).


No necesita definir su propio Table_Row. Sin embargo, puede ser útil en muchos casos, especialmente si desea definir algunos métodos o propiedades específicos para una fila de usuario determinada. También pueden mejorar la legibilidad de tu código.

Por ejemplo, en el caso de la tabla Usuarios, puede definir un método llamado getFullName () en una fila de usuario personalizado como:

public function getFullName() { return $this->firstName . '' '' . $this->lastName; }

Luego, cuando obtienes el objeto fila de usuario, para obtener el nombre completo del usuario, simplemente haces:

$user = $uTable->find($newUid)->current(); $fullName = $user->getFullName();

El segundo ejemplo es cuando tiene una tabla principal en la tabla Usuarios, como Direcciones. En este caso, podría definir un método llamado getAddress en una fila de usuario:

public function getAddress() { return $this->findParentRow(''Application_Model_DbTable_Addresses''); }

En este escenario, obtendría un objeto de fila Dirección para un usuario actual de la siguiente manera:

$user = $uTable->find($newUid)->current(); $addressRow = $user->getAddress();

Otro ejemplo sería cuando desee crear métodos personalizados de eliminación o inserción. Supongamos que desea asegurarse de que no desea eliminar un usuario administrador mediante el método delete (). Luego, puede sobrecargar el método de eliminación de Zend_Db_Table_Row de la siguiente manera:

public function delete() { if (''admin'' === $this->userRole) { return 0; } return parent::delete(); }

De esta forma, no podría eliminar un usuario administrador simplemente llamando a delete () en un objeto de fila de usuario:

$user = $uTable->find($newUid)->current(); $rowsDeleted = $user->delete(); // would be 0 if $user is admin

Estos son solo tres ejemplos básicos que muestran la utilidad de definir sus propias clases de filas. Pero, por supuesto, no son necesarios. Sin embargo, desde mi propia experiencia, son bastante útiles.