phpgetzend-framework2zend-paginator

How to use $_GET with paginator?


I added in my project sorting data by select->order by $GET-variables. But when I navigate through the pages by paginator, of course this variables are not passing on the next page. What is the best way to pass this variables and use it with paginator?

Controller:

public function indexAction()
{
    $sortForm = new \Records\Form\SortingForm();
    $field = 'date';
    $order = 'desc';
    $request = $this->getRequest();

    if ($request->isGet()){
        $sortForm->setValidationGroup(array('field', 'order'));
        $sortData = $request->getQuery()->toArray();
        $sortForm->setData($sortData);

        if($sortForm->isValid()) {
            $sortForm->getData($sortData);
            $field = (string) $this->params()->fromQuery('field', 'date');
            $order = (string) $this->params()->fromQuery('order', 'desc');
        }
    }
    $query = $this->getRecordsTable()->fetchAll($field, $order);

    $paginator = new Paginator\Paginator(new Paginator\Adapter\Iterator($query));
    $paginator->setCurrentPageNumber($this->params()->fromRoute('page', 1));
    $paginator->setItemCountPerPage(25);

    $vm = new ViewModel(array('records' => $paginator));

Model:

public function fetchAll($field, $order)
    {
        $this->field = $field;
        $this->order = $order;
        $resultSet = $this->tableGateway->select(function (Select $select) {
        $select->columns(array('date', 'name', 'email', 'homepage', 'text', 'image', 'file'));
        $select->order($this->field.' '.$this->order);        
        });
        $resultSet->buffer();
        $resultSet->next();

        return $resultSet;
    }

Form:

public function __construct($name = null)
    {
        parent::__construct('records');
        $this->setAttribute('method', 'get');

        $this->add(array(
            'name' => 'field',
            'required' => false,
            'type'  => 'Zend\Form\Element\Select',
            'options' => array(
                'label' => 'Sort by: ',
                'value_options' => array(
                    'date' => 'Date', 
                    'email' => 'E-mail', 
                    'name' => 'Username',
            ),
        )));
        $this->add(array(
            'name' => 'order',
            'required' => false,
            'type'  => 'Zend\Form\Element\Select',
            'options' => array(
                'value_options' => array(
                    'asc' => 'ascending', 
                    'desc' => 'descending', 
            ),
        )));
        $this->add(array(
            'name' => 'submit',
            'attributes' => array(
                'type'  => 'submit',
                'value' => 'Go',
                'id' => 'submitbutton',
            ),
        ));
    }

Paginator view:

<!-- Numbered page links -->
<?php foreach ($this->pagesInRange as $page): ?>
  <?php if ($page != $this->current): ?>
    <a href="<?php echo $this->url($this->route, array('page' => $page)); ?>">
        <?php echo $page; ?>
    </a> |
  <?php else: ?>
    <?php echo $page; ?> |
  <?php endif; ?>
<?php endforeach; ?>

And another one: when I passing get-variables, the query string looks like http://guest-book.me/page/7?field=date&order=asc&submit=Go How I can do not send pair submit=>value?

Thank you for help! :)


Solution

  • Firstly, you need to make sure the route you're using for the Paginator has a Query String child route, I would recommend having a route specifically for use with listings with pagination, an example:

    'router' => array(
        'routes' => array(
           'paginator_route' => array(
                'type' => 'segment',
                'options' => array(
                    'route' => '/list/:controller/:action[/page/:page][/]',
                    'constraints' => array(
                        //'__NAMESPACE__' => 'Application\Controller',
                        'controller'    => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'page'          => '[0-9]+',
                    ),
                    'defaults' => array(
                        'controller' => 'index',
                        'action'     => 'list',
                        'page'       => 1,
                    ),
                ),
                'may_terminate' => true, // with or without Query string
                'child_routes'  => array(
                    'query' => array( // allows us to match query string
                        'type' => 'Query',
                        'options' => array(
                            'defaults' => array(
                                // Query string defaults here..
                            )
                        )
                    ),
                ),
            ),
    

    You now need to modify your pagination view to allow us to use current parameters as a base when generating the new links:

    <!-- Numbered page links -->
    <?php foreach ($this->pagesInRange as $page): ?>
      <?php if ($page != $this->current): ?>
        <?php // the last param allows us to reuse the matched params ?>
        <a href="<?php echo $this->url($this->route, array('page' => $page), TRUE); ?>">
            <?php echo $page; ?>
        </a> |
      <?php else: ?>
        <?php echo $page; ?> |
      <?php endif; ?>
    <?php endforeach; ?>
    

    Your pagination links should now retain the Query string values :-)