Quadro Zend – Perché dovrei usare data mapper / Db_Table_Row?

Domanda estesa: Perché dovrei usare data mapper / Db_Table_Row, where DbTable è in grado di gestire la maggior parte delle attività di base per la manipolazione dei dati.

Attualmente sto imparando ZF v1.11

Per la manipolazione del database, ho creato DbTable per each tabella. Ad esempio, la tabella "utenti" è rappresentata da Application_Model_DbTable_Users senza codici aggiuntivi.

Quando manipolo i dati, posso usare:

<?php $uTable = new Application_Model_DbTable_Users(); $newUid = $uTable->insert(arrays('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(); 

La mia domanda è, quando avrei bisogno di definire una class di row (assumendo che Table_Row sia chiamato DataMapper in ZF-Tutorials)

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

Quali sono i vantaggi di avere una class Row per each entity framework;? Qualcuno può indicarmi le migliori pratiche per questo.

Non è necessario definire il proprio Table_Row. Tuttavia, può essere utile in molti casi, in particolare se si desidera definire alcuni methods o properties; specifici per una determinata row utente. Possono anche migliorare la leggibilità del tuo codice.

Ad esempio nel caso della tabella Utenti, è ansible definire un metodo chiamato getFullName () in una row utente personalizzata come:

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

Quindi, quando ottieni l'object row utente, per get il nome completo dell'utente, devi semplicemente:

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

Il secondo esempio è quando nella tabella Utenti è presente una tabella padre, ad esempio Indirizzi. In questo caso puoi definire un metodo chiamato getAddress in una row utente:

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

In questo scenario, otterresti un object row Indirizzo per un utente corrente come segue:

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

Un altro esempio potrebbe essere quando si desidera creare methods personalizzati di eliminazione o instert. Supponiamo che tu voglia assicurarti di non voler cancellare un utente amministratore usando il metodo delete (). Quindi potresti sovraccaricare il metodo delete da Zend_Db_Table_Row come segue:

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

In questo modo, non sarai in grado di eliminare un utente amministratore semplicemente chiamando delete () su un object row utente:

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

Questi sono solo tre esempi di base che mostrano l'utilità di definire le proprie classi di row. Ma ovviamente non sono necessari. Tuttavia, dalla mia esperienza sono abbastanza utili.

In poche parole: si tratta di isolamento.

Zend_Db_Table è un'implementazione di Table Data Gateway. Canalizza l'accesso CRUD a una vista tabella specifica attraverso una class. Di solito viene utilizzato con un module tabella , ad esempio una class che contiene la logica aziendale per i record gestiti da un gateway.

Zend_Db_Table_Row è un'implementazione del pattern Row Data Gateway . Qui, gli oggetti restituiti appaiono esattamente come un record del database e contengono la logica aziendale per lavorare con quei dati, ma non contengono la logica di CRUD con la tabella da cui provengono (che sarebbe un ActiveRecord) ma li aggregano.

I gateway dati di row vanno bene fintanto che non si dispone di un'eccessiva mancata corrispondenza relazionale dell'impedenza . Il modo in cui un object viene mantenuto in un database relazionale e come dovrebbe apparire in un mondo di oggetti sono spesso cose molto diverse. Quando si utilizza un model di dominio , i propri oggetti di business sono in genere strutturati in modo diverso rispetto a quelli memorizzati nel database. Pertanto, non è ansible CRUD facilmente dal database. È qui che entra in gioco DataMapper .

Un DataMapper si assume la responsabilità di mappare gli oggetti Dominio su Recordset e viceversa. Ciò rende l'applicazione più manutenibile perché disaccoppia gli oggetti Dominio dalla struttura del Database. Li tiene separati e offre maggiore flessibilità su come modellare entrambi i livelli (persistenza e dominio).