2013-05-16 16 views
5

W mojej klasie Mappera rozszerzam AbstractDbMapper z ZfcBase, aby pobrać wiersze z bazy danych. Prostym przykładem jest kodu:Konwertuj Zend Db ResultSet HydratingResultSet do tablicy obiektów

class MyMapper extends AbstractDbMapper 
{ 

    //... 

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

Problemem jest to, że $this->select() zwraca Zend\Db\ResultSet\HydratingResultSet (zawierający potrzebne i uwodnione obiektów). Ale chciałbym zwrócić tablicę tych obiektów zamiast HydratingResultSet zawierających obiekty.

Pierwszą rzeczą, na którą należy spojrzeć, byłby HydratingResultSet::toArray(), ale to zwraca tablicę wielowymiarową zamiast tablicy obiektów.

Więc wybrałem to zrobić ręcznie:

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

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

To działa, ale wygląda brzydko w każdym sprowadzić metodę. Czy muszę zmodyfikować kod z select(), aby uzyskać pożądane zachowanie, czy jest łatwiejszy sposób?

Przy okazji: Czy jest nawet zalecane zwrócić tablicę lub przekonwertować ją w ten sposób? Dzięki za pomoc!

+0

Czy istnieje powód, dla którego potrzebujesz tablicy? Zestaw wyników będzie działał jak iterator i będzie można go używać w większości przypadków. Nie ma wbudowanej metody, aby uzyskać tablicę bez robienia tego, co teraz robisz, możesz dodać tę metodę do swojego programu Mapper lub po prostu Hydrator jako skrót. – Andrew

+0

Używam tych wyników w moim kontrolerze i myślę, że byłoby bardziej czysto pracować z tablicami zamiast z niektórymi obiektami Zend \ Db. Nie rozumiem, dlaczego zdecydowali się to zrobić w ten sposób ... – lorey

+1

zdecydowali się to zrobić w ten sposób, ponieważ otrzymaliście dodatkową funkcjonalność, taką jak buforowanie zestawu wyników itp. Pomyśl o tym, czy masz kolekcję obiektów 9 milionów, tablica stanie się OGROMNA i zużyje pamięć RAM, dzięki tej kolekcji elementy zostaną wykonane na żądanie, jeden po drugim, jest znacznie bardziej wydajny. – Andrew

Odpowiedz

3

Aktualizacja:

Istnieje czystsza możliwość zrobienia tego (przez limuzyny od https://stackoverflow.com/a/19266650/1275778). Dostosowany do mojego przykładu z góry to działa tak:

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

Jeśli limuzyny stanowisk swoją odpowiedź tutaj, będę szczęśliwie zaakceptować.

Old odpowiedź:

Ponieważ nikt nie mógł odpowiedzieć na moje pytanie starałem się wdrożyć najczystszą opcji (do mnie): rozszerzenie AbstractDbMapper dodać wspomnianą funkcjonalność. I udokumentować go tutaj dla każdego, kto szuka rozwiązania:

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() w MyAbstractDbMapper teraz zwraca tablicę obiektów zamiast HydratingResultSet.

W związku z tym, że ktoś może to wyjaśnić, czy ktoś mógłby wyjaśnić, dlaczego?

+1

Lepsze wyjaśnienie i przykład kodu tutaj: http://stackoverflow.com/questions/18940759/how-to-return-an-array-of-objects-in-zend-framework-2?ra=1 –

+0

Dzięki, Bill! Tego właśnie szukałem! Wspaniały! – lorey

1

zwykle już masz klasę obiektu tak więc tylko popupate przypadki twojego obiektu (klasa):

public function fetchById($id) { 

    [...] 

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

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

    return $entries; 
} 

a funkcja Populate mógłby wyglądać następująco:

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

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

    [...] //set other object values 

    return $entry; 
} 

ten zwróci tablicę obiektów

+0

Obiekty w mojej pętli są już wymaganego typu, ponieważ 'HydratedResultSet' zapewnia iterator do zapętlenia się nad uwodnionymi obiektami. Więc to NIE są obiekty wiersza i zostały już uwodnione w 'AbstractDbMapper'. Dlatego nie ma potrzeby funkcji wypełniania i nie trzeba używać funkcji pobierania, ponieważ '$ this-> select()' pobiera wyniki. – lorey

+1

OK. z której wersji Zend korzystasz? Czy 'toArray()' spełnia twoje potrzeby? http://tgaconnect.com/dox/zend/html/class_zend_1_1_db_1_1_result_set_1_1_hydrating_result_set.html#a658defb34762c8f40085aec87e16ba1a – simplyray

+0

Używam ZF 2.2. Nie, toArray() zwraca tablicę wielowymiarową i dlatego nie zawiera żadnych obiektów. – lorey