2008-12-17 11 views
6

Pracuję nad utworzeniem warstwy domeny w Zend Framework, która jest oddzielna od warstwy dostępu do danych. Warstwa dostępu do danych składa się z dwóch głównych obiektów, bramy danych tabeli i bramki danych wiersza. Jak na post Bill Karwin do this earlier question teraz mam następujący kod dla mojej domeny Osoba obiektu:Jak zaprojektować obiekty warstwy domeny do reprezentowania wielu obiektów i pojedynczego obiektu w Zend Framework?

class Model_Row_Person 
{ 
    protected $_gateway; 

    public function __construct(Zend_Db_Table_Row $gateway) 
    { 
     $this->_gateway = $gateway; 
    } 

    public function login($userName, $password) 
    { 

    } 

    public function setPassword($password) 
    { 

    } 
} 

Jednak ta działa tylko z pojedynczego rzędu. Muszę również utworzyć obiekt domeny, który może reprezentować całą tabelę i (prawdopodobnie) może być użyty do iteracji przez wszystkie osoby w tabeli i zwrócenia odpowiedniego typu obiektu (administrator, nabywca, itp.) Do użycia. Zasadniczo, wyobrażam sobie coś takiego:

class Model_Table_Person implements SeekableIterator, Countable, ArrayAccess 
{ 
    protected $_gateway; 

    public function __construct(Model_DbTable_Person $gateway) 
    { 
     $this->_gateway = $gateway; 
    } 

    public function current() 
    { 
     $current = $this->_gateway->fetchRow($this->_pointer); 

     return $this->_getUser($current); 
    } 

    private function _getUser(Zend_Db_Table_Row $current) 
    { 
     switch($current->userType) 
     { 
      case 'admin': 
       return new Model_Row_Administrator($current); 
       break; 
      case 'associate': 
       return new Model_Row_Associate($current); 
       break; 
     } 
    } 
} 

Czy jest to dobry/zły sposób radzenia sobie z tym konkretnym problemem? Jakie ulepszenia lub poprawki powinienem wprowadzić do ogólnego projektu?

Z góry dziękuję za uwagi i uwagi.

Odpowiedz

9

Miałem na uwadze, że można użyć klasy Domain Model, aby całkowicie ukryć fakt, że używasz tabeli bazy danych do utrwalania. Więc przechodząc obiektu tabeli lub obiekt Wiersz powinien być całkowicie pod kołdrę:

<?php 
require_once 'Zend/Loader.php'; 
Zend_Loader::registerAutoload(); 

$db = Zend_Db::factory('mysqli', array('dbname'=>'test', 
    'username'=>'root', 'password'=>'xxxx')); 
Zend_Db_Table_Abstract::setDefaultAdapter($db); 

class Table_Person extends Zend_Db_Table_Abstract 
{ 
    protected $_name = 'person'; 
} 

class Model_Person 
{ 
    /** @var Zend_Db_Table */ 
    protected static $table = null; 

    /** @var Zend_Db_Table_Row */ 
    protected $person; 

    public static function init() { 
     if (self::$table == null) { 
      self::$table = new Table_Person(); 
     } 
    } 

    protected static function factory(Zend_Db_Table_Row $personRow) { 
     $personClass = 'Model_Person_' . ucfirst($personRow->person_type); 
     return new $personClass($personRow); 
    } 

    public static function get($id) { 
     self::init(); 
     $personRow = self::$table->find($id)->current(); 
     return self::factory($personRow); 
    } 

    public static function getCollection() { 
     self::init(); 
     $personRowset = self::$table->fetchAll(); 
     $personArray = array(); 
     foreach ($personRowset as $person) { 
      $personArray[] = self::factory($person); 
     } 
     return $personArray; 
    } 

    // protected constructor can only be called from this class, e.g. factory() 
    protected function __construct(Zend_Db_Table_Row $personRow) { 
     $this->person = $personRow; 
    } 

    public function login($password) { 
     if ($this->person->password_hash == 
      hash('sha256', $this->person->password_salt . $password)) { 
      return true; 
     } else { 
      return false; 
     } 

    } 

    public function setPassword($newPassword) { 
     $this->person->password_hash = hash('sha256', 
      $this->person->password_salt . $newPassword); 
     $this->person->save(); 
    } 
} 

class Model_Person_Admin extends Model_Person { } 
class Model_Person_Associate extends Model_Person { } 

$person = Model_Person::get(1); 
print "Got object of type ".get_class($person)."\n"; 
$person->setPassword('potrzebie'); 

$people = Model_Person::getCollection(); 
print "Got ".count($people)." people objects:\n"; 
foreach ($people as $i => $person) { 
    print "\t$i: ".get_class($person)."\n"; 
} 

„Myślałem, metody statyczne były złe dlatego starałem się stworzyć te metody poziomie tabeli jak np metod . "

nie kupuję do dowolnego zestawienia zbiorcze że static jest zawsze złe, albo singletons zawsze są złe, albo goto zawsze jest złe, albo co ty. Ludzie, którzy składają tak jednoznaczne oświadczenia, starają się uprościć problemy. Używaj narzędzi językowych odpowiednio i będą dla ciebie dobre.

To powiedziawszy, często istnieje kompromis, gdy wybierasz konstrukcję jednego języka, ułatwia to wykonywanie pewnych czynności, podczas gdy trudniej jest robić inne rzeczy. Ludzie często wskazują na static, co utrudnia napisanie kodu testu jednostkowego, a także PHP ma pewne irytujące braki związane z ładowaniem statycznym i podklasami. Ale są też zalety, jak widzimy w tym kodzie. Musisz sam ocenić, czy zalety przeważają nad wadami, na podstawie każdego przypadku.

"Czy Zend Framework obsługuje klasę Finder ?"

Nie sądzę, że to konieczne.

„Czy jest jakiś szczególny powód, że przemianowany metody znajdowania się być w klasy modelką?”

Nazwę metodę get(), aby odróżnić się od find(). Paradygmat "getter" jest powiązany z interfejsami OO, podczas gdy "finders" są tradycyjnie kojarzone z bazą danych. Próbujemy zaprojektować model domeny, aby udawać, że nie ma w nim bazy danych.

„I byłoby użyć nadal korzystać z samej logiki do realizacji specyficznych getBy i metody getCollectionBy?”

bym oprzeć tworząc ogólną getBy() metodę, ponieważ jest to kuszące, aby zaakceptować ogólne wyrażenie SQL, a następnie przekazać je do obiektów dostępu do danych Verbatim. Wiąże się to z wykorzystaniem naszego Modelu Domeny do podstawowej reprezentacji bazy danych.

+0

BTW, użyłem tego jako ćwiczenia, aby nauczyć się kodu PHP w nowym NetBeans 6.5. To rządzi! –

+0

Dwa pytania: 1) Myślałem, że metody statyczne są złe, dlatego próbowałem stworzyć metody na poziomie tabeli jako metody instancji. Czy Zend Framework obsługuje klasę Finder? –

+0

2) Czy jest jakiś szczególny powód, dla którego zmieniono nazwę metody wyszukiwania na klasę modelu? Czy używałbyś nadal tej samej logiki do implementacji konkretnych metod getBy i getCollectionBy? –

Powiązane problemy