2008-12-17 25 views
6

Tôi đang làm việc để tạo lớp miền trong Zend Framework tách biệt với lớp truy cập dữ liệu. Lớp truy cập dữ liệu bao gồm hai đối tượng chính, một cổng dữ liệu bảng và một cổng dữ liệu hàng. Theo trả lời Bill Karwin để this earlier question bây giờ tôi có đoạn mã sau cho đối tượng Person tên miền của tôi:Làm thế nào để thiết kế các đối tượng lớp miền để biểu diễn nhiều đối tượng và đối tượng đơn trong khung công tác Zend?

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) 
    { 

    } 
} 

Tuy nhiên, điều này chỉ làm việc với một hàng cá nhân. Tôi cũng cần phải tạo một đối tượng miền có thể đại diện cho toàn bộ bảng và (có lẽ) có thể được sử dụng để lặp qua tất cả các Person trong bảng và trả về kiểu người thích hợp (admin, người mua, vv) để sử dụng. Về cơ bản, tôi hình dung một cái gì đó như sau:

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; 
     } 
    } 
} 

Đây có phải là tốt/xấu cách nào để xử lý các vấn đề cụ thể này? Tôi nên thực hiện những cải tiến hoặc điều chỉnh nào đối với thiết kế tổng thể?

Cảm ơn bạn trước vì đã bình luận và phê bình.

Trả lời

9

Tôi đã nhớ rằng bạn sẽ sử dụng lớp Mô hình miền để ẩn hoàn toàn thực tế rằng bạn đang sử dụng bảng cơ sở dữ liệu để duy trì sự kiên trì. Vì vậy, thông qua một đối tượng Table hoặc một đối tượng Row nên hoàn toàn theo bao gồm:

<?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"; 
} 

"Tôi nghĩ phương pháp tĩnh đã xấu đó là lý do tôi đã cố gắng để tạo ra các phương pháp mức bảng như ví dụ phương pháp . "

Tôi không mua vào bất kỳ tuyên bố rằng chăn static luôn là xấu, hoặc độc thân luôn xấu, hoặc goto phải lúc nào cũng xấu, hoặc những gì có bạn. Những người đưa ra những tuyên bố rõ ràng như vậy đang tìm cách đơn giản hoá các vấn đề. Sử dụng các công cụ ngôn ngữ phù hợp và chúng sẽ tốt cho bạn.

Điều đó nói rằng, thường có sự cân bằng khi bạn chọn một cấu trúc ngôn ngữ, nó giúp bạn dễ dàng thực hiện một số việc trong khi khó làm những việc khác. Mọi người thường trỏ đến static khiến việc viết mã thử nghiệm đơn vị trở nên khó khăn và PHP cũng có một số thiếu sót gây phiền nhiễu liên quan đến tĩnh và phân lớp. Nhưng cũng có những ưu điểm, như chúng ta thấy trong đoạn mã này. Bạn phải tự đánh giá liệu các ưu điểm có vượt trội hơn những nhược điểm hay không, trên cơ sở từng trường hợp.

"Zend Framework có hỗ trợ tìm kiếm lớp không?"

Tôi không nghĩ điều đó là cần thiết.

"Có một lý do cụ thể mà bạn đổi tên là tìm phương pháp để có được trong lớp mô hình?"

Tôi đặt tên phương thức get() chỉ để tách biệt với find(). Mô hình "getter" được liên kết với các giao diện OO, trong khi "người tìm" theo truyền thống được kết hợp với các công cụ cơ sở dữ liệu. Chúng tôi đang cố gắng thiết kế Mô hình miền để giả vờ không có cơ sở dữ liệu nào liên quan.

"Và bạn sẽ sử dụng tiếp tục sử dụng cùng logic để thực hiện cụ thể getBy và phương pháp getCollectionBy?"

Tôi muốn chống lại việc tạo phương thức chung getBy(), bởi vì nó hấp dẫn để làm cho nó chấp nhận một biểu thức SQL chung, và sau đó chuyển nó vào các đối tượng truy cập dữ liệu nguyên văn. Điều này kết hợp việc sử dụng Mô hình miền của chúng tôi với cơ sở dữ liệu bên dưới.

+0

BTW, tôi đã sử dụng bài tập này để tìm hiểu cách viết mã PHP trong NetBeans 6.5 mới. Nó đá! –

+0

Hai câu hỏi: 1) Tôi nghĩ rằng phương pháp tĩnh là xấu đó là lý do tại sao tôi đã cố gắng để tạo ra các phương pháp mức bảng như phương pháp dụ. Zend Framework có hỗ trợ lớp Finder không? –

+0

2) Có lý do cụ thể nào mà bạn đã đổi tên phương thức tìm kiếm để có được trong lớp mô hình không? Và bạn sẽ sử dụng tiếp tục sử dụng cùng một logic để thực hiện các phương thức getBy và getCollectionBy cụ thể? –

Các vấn đề liên quan