I naprawdę Potrzebowaliśmy rozwiązania, w których mogę użyć Zend_Db_Table metody klasy jako źródło mojego adaptera paginator zamiast tablicy lub obiektu Zend_Db_Select.
Ten rodzaj zaawansowanego modelowania nie jest zgodny ze standardowymi adapterami dla Zend_Paginator. Poszedłem naprzód i naprawiłem to dla każdego, kto desperacko szuka odpowiedzi, tak jak ja.
<?php
/* /zend/Paginator/Adapter/DbTableMethod.php */
class Zend_Paginator_Adapter_DbTableMethod implements Zend_Paginator_Adapter_Interface {
protected $_class;
protected $_method;
protected $_parameters;
protected $_rowCount = null;
public function __construct($class, $method, array $parameters = array()){
$reflectionClass = new ReflectionClass($class);
$reflectionMethod = $reflectionClass->getMethod($method);
$reflectionParameters = $reflectionMethod->getParameters();
$_parameters = array();
foreach ($reflectionParameters as $reflectionParameter){
$_parameters[$reflectionParameter->name] = ($reflectionParameter->isDefaultValueAvailable()) ? $reflectionParameter->getDefaultValue() : null;
}
foreach ($parameters as $parameterName => $parameterValue){
if (array_key_exists($parameterName, $_parameters)) $_parameters[$parameterName] = $parameterValue;
}
$this->_class = $class;
$this->_method = $method;
$this->_parameters = $_parameters;
}
public function count(){
if (is_null($this->_rowCount)){
$parameters = $this->_parameters;
$parameters['count'] = true;
$this->_rowCount = call_user_func_array(array($this->_class, $this->_method), $parameters);
}
return $this->_rowCount;
}
public function getItems($offset, $itemCountPerPage){
$parameters = $this->_parameters;
$parameters['limit'] = $itemCountPerPage;
$parameters['offset'] = $offset;
$items = call_user_func_array(array($this->_class, $this->_method), $parameters);
return $items;
}
}
?>
Jak to działa w kontrolerze:
<?php
class StoreController extends Zend_Controller_Action {
public function storeCustomersAction(){
$model = new Default_Model_Store();
$method = 'getStoreCustomers';
$parameters = array('storeId' => 1);
$paginator = new Zend_Paginator(new Site_Paginator_Adapter_DbTableMethod($model, $method, $parameters));
$paginator->setCurrentPageNumber($this->_request->getParam('page', 1));
$paginator->setItemCountPerPage(20);
$this->view->paginator = $paginator;
}
}
?>
Jedyne wymagania dla tego adaptera do pracy jest notować następujące parametry w liście metody argumenty modelu (w dowolnej kolejności [adaptera wykryje podpis metody poprzez odbicie):
$ limit = 0, $ offset = 0, $ count = false
Paginator wywoła metodę z odpowiednimi wartościami dla argumentów $ limit, $ offset i $ count. To jest to!
Przykład:
<?php
class Default_Model_Store extends Zend_Db_Table {
public function getStoreCustomers($storeId, $includeCustomerOrders = false, $limit = 0, $offset = 0, $count = false){
if ($count) /* return SELECT COUNT(*) ... */
/* ... run primary query, get result */
$select = $this->_db->select(...)->limit($limit, $offset);
$rows = $this->_db->fetchAll($select);
if ($includeCustomerOrders){
foreach ($rows as &$row){
$customerId = $row['id'];
$row['orders'] = $this->getCustomerOrders($customerId);
}
}
return $rows;
}
}
?>
Ale nie to wydawać marnotrawstwem? Wywołanie getAll() - kosztowne połączenie, które może zwracać tysiące lub miliony rekordów - a następnie zignorować wszystkie z wyjątkiem 20, które mogą być potrzebne dla jednej strony wyświetlanych danych? –