2013-05-16 30 views
5

Trong lớp Mapper của tôi, tôi mở rộng AbstractDbMapper từ ZfcBase để tìm nạp các hàng từ cơ sở dữ liệu. Một ví dụ đơn giản sẽ là mã như thế này:Chuyển đổi Zend Db ResultSet HydratingResultSet thành Mảng đối tượng

class MyMapper extends AbstractDbMapper 
{ 

    //... 

    public function fetchAll() { 
     $select = $this->getSelect(); 
     return $this->select($select); // returns HydratingResultSet 
    } 
} 

Vấn đề là $this->select() trả về một Zend\Db\ResultSet\HydratingResultSet (chứa các đối tượng cần thiết và ngậm nước). Nhưng tôi muốn trả về một mảng các đối tượng này thay vì HydratingResultSet chứa các đối tượng.

Điều đầu tiên để xem xét sẽ là HydratingResultSet::toArray() nhưng điều này trả về mảng đa chiều thay vì một mảng đối tượng.

Vì vậy, tôi đã chọn để làm điều đó bằng tay:

public function fetchAll() { 
     $select = $this->getSelect(); 

     $results = array(); 
     foreach ($this->select($select) as $object) { 
      $results[] = $object; 
     } 
     return $results; // returns array of needed objects 
} 

này hoạt động nhưng trông xấu xí trong mọi phương pháp lấy. Tôi có phải sửa đổi mã từ select() để có được hành vi mong muốn hoặc có cách nào dễ dàng hơn không?

Btw: Thậm chí nó được đề nghị trả về một mảng hay chuyển đổi nó như thế này? Cảm ơn bạn đã giúp đỡ!

+0

Có lý do nào bạn cần một mảng không? Các Resultet sẽ làm việc như một iterator tốt và có thể được sử dụng trong hầu hết các trường hợp .. Không có phương pháp tích hợp để lấy mảng mà không làm những gì bạn đang làm bây giờ, bạn có thể thêm phương thức vào Mapper của bạn hoặc một Hydrator chỉ như một đường tắt. – Andrew

+0

Tôi đang sử dụng các kết quả này trong Bộ điều khiển của mình và cho rằng nó sẽ sạch hơn khi hoạt động với các mảng thay vì một số đối tượng Zend \ Db. Tôi không hiểu tại sao họ lại chọn cách này ... – lorey

+1

họ chọn làm theo cách này bởi vì bạn nhận được thêm chức năng, chẳng hạn như đệm bộ kết quả, vv Hãy suy nghĩ về nếu bạn có bộ sưu tập 9million đối tượng, bạn sẽ trở thành HUGE và tiêu thụ RAM, với bộ sưu tập này theo yêu cầu tại một thời điểm, nó hiệu quả hơn nhiều. – Andrew

Trả lời

3

Cập nhật:

Có khả năng làm sạch hơn (bằng xe limo từ https://stackoverflow.com/a/19266650/1275778). Thích nghi với ví dụ của tôi từ trên cao nó hoạt động như thế này:

public function fetchAll() { 
    $select = $this->getSelect(); 
    $results = $this->select($select); 
    return \Zend\Stdlib\ArrayUtils::iteratorToArray($results); // returns desired array of objects 
} 

Nếu limos đăng câu trả lời của mình ở đây, tôi sẽ vui vẻ chấp nhận nó.

Cũ câu trả lời:

Kể từ khi không ai có thể trả lời câu hỏi của tôi, tôi đã cố gắng để thực hiện các lựa chọn sạch (với tôi): mở rộng AbstractDbMapper để thêm các chức năng đề cập. Tôi ghi lại nó ở đây cho bất cứ ai tìm kiếm một giải pháp:

MyAbstractDbMapper extends AbstractDbMapper 
{ 
    /** 
    * @param Select $select 
    * @param object|null $entityPrototype 
    * @param HydratorInterface|null $hydrator 
    * @return array 
    */ 
    protected function select(Select $select, $entityPrototype = null, 
     HydratorInterface $hydrator = null) 
    { 
     $resultSet = parent::select($select, $entityPrototype, $hydrator); 
     $results = array(); // Array of result objects 
     foreach ($resultSet as $object) { 
      $results[] = $object; 
     } 
     return $results; 
    } 
} 

select() trong MyAbstractDbMapper tại trả về một mảng các đối tượng thay vì HydratingResultSet.

Vì điều này bị giảm giá, có thể ai đó vui lòng giải thích lý do tại sao?

+1

Giải thích và ví dụ mã tốt hơn ở đây: http://stackoverflow.com/questions/18940759/how-to-return-an-array-of-objects-in-zend-framework-2?ra=1 –

+0

Cảm ơn, Bill! Đó là những gì tôi đang tìm kiếm! Tuyệt quá! – lorey

1

thường bạn đã có các lớp đối tượng anyway vì vậy trường hợp chỉ popupate của đối tượng của bạn (class):

public function fetchById($id) { 

    [...] 

    $resultSet = $this->getDbTable()->fetchAll($select); 
    $entries = array(); 

    foreach ($resultSet as $row) { 
     $entries[] = $this->populate($row); 
    } 

    return $entries; 
} 

và chức năng populate có thể trông giống như thế này:

private function populate($row) 
{ 
    $entry = new Application_Model_YourModel(); 

    $entry->setId($row->id); 

    [...] //set other object values 

    return $entry; 
} 

này sẽ trả về một mảng đối tượng

+0

Các đối tượng trong vòng lặp của tôi đã có loại cần thiết như 'HydratedResultSet' cung cấp một trình lặp để lặp qua các đối tượng ngậm nước. Vì vậy, đây không phải là đối tượng hàng và đã được ngậm nước trong 'AbstractDbMapper'. Do đó không cần một hàm điền và không cần sử dụng hàm fetchAll vì '$ this-> select()' đang tìm nạp kết quả. – lorey

+1

OK. bạn đang sử dụng phiên bản zend nào? 'ToArray()' có đáp ứng nhu cầu của bạn không? http://tgaconnect.com/dox/zend/html/class_zend_1_1_db_1_1_result_set_1_1_hydrating_result_set.html#a658defb34762c8f40085aec87e16ba1a – simplyray

+0

Tôi đang sử dụng ZF 2.2. Không, toArray() trả về mảng đa chiều và do đó không chứa đối tượng nào cả. – lorey