2011-01-30 14 views
22

Poszerzone pytanie: dlaczego powinienem używać programu odwzorowującego dane/Db_Table_Row, gdzie jako DbTable jest w stanie obsłużyć większość podstawowych zadań manipulowania danymi.Zend Framework - Dlaczego powinienem używać programu odwzorowującego dane/Db_Table_Row?

Obecnie uczę ZF v1.11

do manipulacji danych, stworzyłem DbTable dla każdej tabeli. Na przykład tabela "users" jest reprezentowana przez Application_Model_DbTable_Users bez żadnych dodatkowych kodów.

Kiedy manipulowania danymi, mogę użyć:

<?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(); 

Moje pytanie brzmi, kiedy muszę zdefiniować klasę wierszy (zakładając Table_Row jest określany jako DataMapper w ZF-Tutorials)

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

Jakie są zalety posiadania klasy Row dla każdej jednostki? Czy każdy może wskazać mi najlepsze praktyki w tym zakresie.

+0

http://stackoverflow.com/questions/373054/ - daje pomysł, że wysyłanie wiadomości e-mail lub zmiana logiki hasła może być zaimplementowana w klasie Wiersz tabeli, która jest specyficzna dla użytkownika. –

Odpowiedz

41

Nie trzeba definiować własnego Table_Row. Może jednak być przydatny w wielu przypadkach, szczególnie jeśli chcesz zdefiniować określone metody lub właściwości dla danego wiersza użytkownika. Mogą również poprawić czytelność kodu.

Na przykład w Twoim przypadku tabeli użytkowników, można określić metodę zwaną getFullName() w niestandardowych rzędu użytkownika jako:

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

Wtedy, kiedy uzyskać obiekt wiersz użytkownika, aby uzyskać pełną nazwę z użytkownikiem, wystarczy zrobić:

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

Drugi przykład jest, gdy masz jakieś tabeli nadrzędnej w tabeli użytkowników, takich jak adresy. W tym przypadku można zdefiniować metodę zwaną getAddress w rzędzie użytkownika:

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

W tym scenariuszu, co można uzyskać obiekt Adres wiersza dla bieżącego użytkownika w następujący sposób:

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

Innym przykładem, byłby wtedy, gdy chcesz utworzyć niestandardowe metody usuwania lub instert. Załóżmy, że chcesz się upewnić, że nie chcesz usuwać administratora przy użyciu metody delete(). Następnie można przeciążyć metodę Usuń z Zend_Db_Table_Row następująco:

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

ten sposób, że nie będzie w stanie usunąć użytkownika admin tylko poprzez wywołanie delete() na obiekcie rzędu użytkownika:

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

To tylko trzy podstawowe przykłady pokazujące przydatność definiowania własnych klas wierszy. Ale oczywiście nie są one konieczne. Jednak z własnego doświadczenia są one bardzo przydatne.

+0

Awesome !!! Dzięki za prawdziwe kody przykładowe z wyjaśnieniem: -] –

+0

+1 Rzeczywiście, bardzo ładnie. –

+0

W odpowiedzi na pytanie # 373054, istnieje funkcja sendMailTo dla użytkownika, czy dobrą praktyką jest zachowanie funkcji związanych z bazami danych w klasie Db_Row? Gdzie powinna znajdować się logika biznesowa specyficzna dla użytkownika? –

20

Krótko mówiąc: chodzi o izolację.

Zend_Db_Table jest implementacją bramy danych tabeli. Umożliwia kanałowi CRUD dostęp do określonego widoku tabeli przez jedną klasę.Jest zwykle używany z Table Module, np. klasa zawierająca logikę biznesową dla rekordów obsługiwanych przez bramkę.

Zend_Db_Table_Row jest implementacją Row Data Gateway Pattern. Tutaj zwrócone obiekty wyglądają dokładnie tak, jak rekord bazy danych i zawierają logikę biznesową do pracy z tymi danymi, ale nie zawierają logiki do CRUD z tabelą, z której pochodzą (to byłaby ActiveRecord), ale agregują je.

Bramki danych wierszy są w porządku, o ile nie masz zbyt wiele object relational impedance mismatch. To, jak obiekt jest utrzymywany w relacyjnej bazie danych i jak powinien wyglądać w świecie obiektów, często jest zupełnie inną sprawą. Podczas korzystania z obiektu Domain Model obiekty biznesowe mają zwykle inną strukturę niż są przechowywane w bazie danych. W związku z tym nie można w prosty sposób zasymulować ich z bazy danych. To tutaj wchodzi w grę DataMapper.

DataMapper bierze odpowiedzialność za odwzorowywanie obiektów domen na zestawy rekordów i odwrotnie. To sprawia, że ​​twoja aplikacja jest łatwiejsza w utrzymaniu, ponieważ oddziela twoje obiekty domeny od struktury bazy danych. Zachowuje je w separacji i zapewnia większą elastyczność w modelowaniu obu warstw (trwałości i domeny).