Zend Framework 2 Пагинатор + TableGateway

Как использовать картограф базы данных с пагинатором?

У меня возникли проблемы с пониманием того, как я реализую разбиение на страницы DbSelect, используя приведенный ниже код (сейчас он использует адаптер Iterator, который не работает для ResultSets).

Из того, что я могу сказать, это не так прямолинейно, как я надеялся. DbSelect ожидает Zend\Db\Sql\Select и адаптер. Адаптер не является проблемой и может быть получен с помощью:

$this->newsContents()->getAdapter()

но у меня возникли проблемы с получением объекта Select из моего TableGateway без дублирования моего кода запроса. Есть ли простой способ решить эту проблему?

NewsController.php

<?php

namespace News\Controller;

use Zend\Paginator\Paginator;

class NewsController extends \Application\Controller\WebsiteController
{
    protected $newsTable;

    protected $newsContents;

    protected function newsTable()
    {
        return $this->getServiceLocator()->get('News\Model\NewsTable');
    }

    protected function newsContents()
    {
        return $this->getServiceLocator()->get('News\Model\NewsContentsTable');
    }

    protected function articleId()
    {
        return (int) $this->params()->fromRoute('id');
    }

    public function articleAction()
    {
        $article = $this->newsTable()->getArticle($this->articleId());
        $pages   = $this->newsContents()->getPages($this->articleId());

        $paginator = new Paginator(new \Zend\Paginator\Adapter\Iterator($pages));
        $paginator->setCurrentPageNumber($this->params()->fromRoute('page'));

        return array(
            'css'       => 'news.css',
            'article'   => $article,
            'paginator' => $paginator,
        );
    }
}

NewsContentsTable.php

<?php

namespace News\Model;

use Zend\Db\Adapter\Adapter;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\AbstractTableGateway;
use Zend\Db\Sql\Select;

class NewsContentsTable extends \Zend\Db\TableGateway\AbstractTableGateway
{
    protected $table = 'news_contents';

    public function __construct(Adapter $adapter)
    {
        $this->adapter = $adapter;
        $this->resultSetPrototype = new ResultSet;
        $this->resultSetPrototype->setArrayObjectPrototype(new NewsContents);
        $this->initialize();
    }

    public function getPages($newsId)
    {
        $rowset = $this->select(function(Select $select) use ($newsId)
        {
            $select
                ->order('order ASC')
                ->where(array('news_id' => $newsId));
        });

        return $rowset;
    }

}

person The Pixel Developer    schedule 15.09.2012    source источник


Ответы (5)


Реализация пагинатора с DbSelect в качестве адаптера

// controller
public function articleAction()
{
    //...
    $paginator = $this->newsContents()->getPages($this->articleId());
    $paginator->setCurrentPageNumber($this->params()->fromRoute('page'));

    return array(
        'css'       => 'news.css',
        'article'   => $article,
        'paginator' => $paginator,
    );
}
?>

// table
public function getPages($newsId)
{
    $sql = $this->getSql();
    $select = $sql->select();
    $select->where(array('news_id' => $newsId))->order('id ASC');
    $adapter = new \Zend\Paginator\Adapter\DbSelect($select, $sql);
    $paginator = new \Zend\Paginator\Paginator($adapter);
    return $paginator;
}
person Elvan    schedule 04.10.2012
comment
Спасибо за ваш ответ, похоже, это самый правильный из предоставленных. - person The Pixel Developer; 06.10.2012
comment
Хороший ответ, но как работает этот пагинатор? Сам класс добавит ограничение и смещение к запросу на основе setCurrentPageNumber() или setItemCountPerPage()? .... или просто использовать что-то вроде array_slice()?... я уверен, что это умнее, чем это. Верно? - person Drk_alien; 17.03.2016

Начиная с Zend Framework 2.2 это намного проще (и позволяет вам в полной мере насладиться преимуществами, предлагаемыми TableGateway) - вы должны использовать

use Zend\Db\TableGateway\TableGateway;
use Zend\Paginator\Paginator;
use Zend\Paginator\Adapter\DbTableGateway;  // !!!

 
$dbTableGatewayAdapter = new DbTableGateway($this->tableGateway);
$paginator = new Paginator($dbTableGatewayAdapter);
return $paginator;
person Tomek Kobyliński    schedule 21.06.2013

но у меня возникли проблемы с получением объекта Select из моего TableGateway без дублирования моего кода запроса. Есть ли простой способ решить эту проблему?

Вы можете получить объект select внутри класса NewsContentsTable следующим образом:

$this->getSql()->select();
person Andrew    schedule 04.10.2012

Используйте buffer() и next() перед возвратом в $rowset.

$rowset->buffer();
$rowset->next();

return $rowset;
person samsonasik    schedule 25.09.2012

Вот пример кода для разбивки на страницы в ZF2

 <?php
    //var/www/html/zend_app/module/Application/src/Application/Controller/Plugin/MyCustomPlugin.php
    namespace Application\Controller\Plugin;

    use Zend\View\Helper\AbstractHelper;

    use Zend\Db\Adapter\Adapter;
    use Zend\Db\ResultSet\ResultSet;
    use Zend\Db\Sql\Select;
    use Zend\Db\Sql\Sql;
    use Zend\Db\Sql\Where;

    use Zend\Mvc\Controller\Plugin\AbstractPlugin;

    use Zend\Paginator\Paginator;
    use Zend\Paginator\Adapter\Iterator as paginatorIterator;
    use Zend\Paginator\Adapter\DbSelect;

    class MyCustomPlugin extends AbstractPlugin {

        protected $adapter;

        public function __construct(\Zend\Db\Adapter\Adapter $adapter) {
            $this->adapter = $adapter;
        }




         public function getPaginatedTableData($tableName, $whereData = "", $selectedColumn = '' , $currentPageNumber = 1) {

            $sql = new Sql($this->adapter);
            $select = $sql->select();

            if ($selectedColumn) {
                $select->columns($selectedColumn);
            }
            $select->from($tableName);
            if ($whereData) {
                $select->where($whereData);
            }

            $paginator = $this->getPaginatorForSelect($select, $currentPageNumber);


            $resultSet = new ResultSet;
            $resultSet->initialize($paginator);
            $resultSet->buffer();

              $pagination = array(
               'current_page_number'=>$currentPageNumber,
               'page_count'=>$paginator->getPages()->pageCount,
               'previous'=>isset($paginator->getPages()->previous)?$paginator->getPages()->previous:0,
               'next'=>isset($paginator->getPages()->next)?$paginator->getPages()->next:0,
               );


 return ($resultSet &&  0 != $paginator->getPages()->pageCount)?array('resultSet'=>$resultSet->toArray(), 'pagination'=>$pagination):FALSE;

        }




        public function getPaginatorForSelect($select, $page, $limit=2)
    {
    $paginatorAdapter = new DbSelect($select, $this->adapter);
    $paginator = new Paginator($paginatorAdapter);
    $paginator->setItemCountPerPage($limit);
    $paginator->setPageRange(5);
    $paginator->setCurrentPageNumber($page);
    return $paginator;
    }

    }

ХТН

person Faiyaz Alam    schedule 06.05.2016