Cakephp and paginating multiple result sets

前端 未结 2 1688
后悔当初
后悔当初 2021-01-15 00:30

I have pagination working fine for when $this->paginate is called once in an action, but it does not appear to be very good support for multiple calls. Here is what I\'m loo

相关标签:
2条回答
  • 2021-01-15 00:57

    I had the same problem and solved the problem with the following Classes in cakephp version 2.5.3 I have not checked whether my approach also works in older versions. First, I created a Helper and Component class which extends PaginationComponent and PaginationHelper and overwrote some Methods.

    /app/Controller/Component/_PaginatorComponent.php

    <?php
    /**
     * Filename:    _PaginatorComponent.php
     * User:        Mitja Stelzner
     * Date:        18.01.14
     */
    App::import('Component', 'Paginator');
    class _PaginatorComponent extends PaginatorComponent{
        public function paginate($object = null, $scope = array(), $whitelist = array())
        {
            //Adopt from the beginning of parent::paginate
            if (is_array($object))
                $object = null;
            $object = $this->_getObject($object);
    
            $options = $this->mergeOptions($object->alias); //get options
            $params = $this->Controller->request->params; //get params
    
            //if custom page name is set
            if(isset($params['named'][$options['pageRequestName']]))
            {
                //get the page number and set it as 'page' in the request (for other methods in the Component)
                $page = $params['named'][$options['pageRequestName']];
                $this->Controller->request->params['named']['page'] =intval($page);
            }
            else
                $this->Controller->request->params['named']['page'] = 1; //else set the page number to 1
    
            $pageRequestName = null; //important for parent::paginate
    
            $results = parent::paginate($object, $scope, $whitelist); // TODO: Change the autogenerated stub
            unset($this->Controller->request->params['named']['page']); //remove the appended page number
    
            //get the options again
            $options = $this->mergeOptions($object->alias);
            //and add the pageRequestName to the paging array
            if(isset($options['pageRequestName']))
            $this->Controller->request['paging'] = array_merge_recursive(
                (array)$this->Controller->request['paging'],
                array($object->alias => array('pageRequestName'=>$options['pageRequestName']))
            );
            return $results;
        }
    
    }
    

    /app/View/Helper/_PaginatorHelper.php

    <?php
    /**
     * Filename:    _PaginatorHelper.php
     * User:        Mitja Stelzner
     * Date:        18.01.14
     */
    App::uses('PaginatorHelper', 'View/Helper');
    class _PaginatorHelper extends PaginatorHelper{
        public function link($title, $url = array(), $options = array()) {
            //change the page parameter 'page' to the custom pageRequestName
            if(isset($url['page']))
            {
                $params = $this->params($this->model);
                if(isset($params['pageRequestName']))
                {
                    $url[$params['pageRequestName']] = $url['page'];
                    unset($url['page']);
                }
            }
            return parent::link($title,$url,$options);
        }
    
        protected function _pagingLink($which, $title = null, $options = array(), $disabledTitle = null, $disabledOptions = array())
        {
            //Prevent the deletion of the variable model
            $disabledOptions['model'] = $options['model'];
            return parent::_pagingLink($which, $title, $options, $disabledTitle, $disabledOptions); // TODO: Change the autogenerated stub
        }
    
        private $model = null;
        public function numbers($options = array())
        {
            //Only to set the model again
            if(isset($options['model']))
                $this->model = $options['model'];
            return parent::numbers($options); // TODO: Change the autogenerated stub
        }
    
    
    }
    

    And a View Element to use the Pagination quickly:

    /app/View/Element/paging.ctp

    <div class="paging">
        <?php
        $options = !isset($modelName)?array():array('model'=>$modelName);
        echo $this->Paginator->prev('< ' . __('zurück'), $options, null, array('class' => 'prev disabled'));
        echo $this->Paginator->numbers(array('separator' => '')+$options);
        echo $this->Paginator->next(__('vor') . ' >', $options, null, array('class' => 'next disabled'));
        ?>
    </div>
    

    You can call the paging-element in your view like this: (Documentation)

    <?php
    echo $this->element('paging',array('modelName'=>'Customer'));
    ?>
    

    If you want use the new created paginator, you have to say cakephp to use your class instead of the normal paginator. In your controller, you set the PaginatorHelper and PaginatorComponent like this: (found here)

    public $helpers = array('Paginator' => array('className' => '_Paginator' ));
    public $components = array('Paginator' => array('className' => '_Paginator' ));
    

    The usage inside your controller. The $paginate have to be grouped into the Modelgroups: (Documentation)

    public $paginate = array(
            'Customer' => array (
                'limit' => 25,
                'pageRequestName' => 'cpage'
            ),
            'Employer' => array (
                'limit' => 25,
                'pageRequestName' => 'erpage'
            ),
            'Employee' => array (
                'limit' => 25,
                'pageRequestName' => 'eepage'
            )
        );
    

    But I use it in the following context:

    $this->Paginator->settings['Customer'] = array(
                'conditions'=>array(
                    'OR'=>array(
                        array('name LIKE'=>'%'.$search_query.'%'),
                    )
                ),
                'limit' => 5,
                'pageRequestName' => 'cpage'
            );
            $result = $this->Paginator->paginate('Customer');
    

    I hope I could help some people who do not want a javascript hack, but a real possibility to have several Paginations on one side.

    At the moment you can only use 'paramType' => 'named'

    In my opinion, the original code in PaginationComponent and PaginationHelper are horrible to read, extend and adapt.

    0 讨论(0)
  • 2021-01-15 01:12

    Since there was not much activity on this, I went ahead and did the reasonable thing and figured out a workaround. Below is what I came up with:

    Controller:

    function index() {
        $active = $this->paginate('Post', array('Post.status'=>1));     
        $activePaging = $this->request->params['paging']['Post'];
    
        $inactive = $this->paginate('Post', array('Post.status'=>0));
        $inActivePaging = $this->request->params['paging']['Post'];
    
        $this->set('active', $active);
        $this->set('inactive', $inactive);
    
        $this->request->params['paging']['Active'] = $activePaging;
        $this->request->params['paging']['InActive'] = $inActivePaging;
        unset($this->request->params['paging']['Post']);
    }
    
    public function paginate() {
        if ($this->request->is('ajax')) {
            $model = $this->request->params['named']['model'];
            $status = $model === 'Active' ? 1 : 0;
    
            $posts = $this->paginate('Post', array('Post.status'=>$status));
            $paging = $this->request->params['paging']['Post'];
            unset($this->request->params['paging']['Post']);
            $this->request->params['paging'][$model] = $paging;
    
            $this->set('posts', $posts);
            $this->set('model', $model);
            $this->render('/Posts/ajax_posts_paginated', 'ajax');
        }
    }
    

    Views: (simplified)

    index.ctp

    <h3>Inactive Posts</h3>
    <div class="well" id="InActive">
    <?php echo $this->element('posts_table_paginated', array('posts'=>$inactive, 'model'=>'InActive')); ?>
    </div>
    
    <h3>Active Posts</h3>
    <div class="well" id="Active">
    <?php echo $this->element('posts_table_paginated', array('posts'=>$active, 'model'=>'Active')); ?>
    </div>
    

    elements/posts_table_paginated.ctp

    <?php
    $this->Paginator->options(array(
        'update' => '#'.$model,
        'evalScripts' => true,
        'url'=> array('controller'=>'posts', 'action'=>'paginate', 'model'=>$model)
    ));
    ?>
    <table>
        <tr>
            <th><?php echo $this->Paginator->sort('id', 'ID', array('model'=>$model)); ?></th>
            <th><?php echo $this->Paginator->sort('title', 'Title', array('model'=>$model)); ?></th>
            <th><?php echo $this->Paginator->sort('created', 'Created', array('model'=>$model)); ?></th>
            <th>Created by</th>
        </tr>
        <?php 
        foreach ($posts as $post): 
        ?>
        <tr>
            <td><?php echo $post['Post']['id']; ?></td>
            <td><?php echo $post['Post']['title']; ?></td>
            <td><?php echo $post['Post']['created']; ?></td>
            <td><?php echo $post['User']['username']; ?></td>
        </tr>
        <?php 
        endforeach; 
        ?>
    </table>
    <?php
        if ($this->params['paging'][$model]['count'] > 0) {
    ?>
    <div id="pagination">
        <ul id="paginate">
            <?php
                echo $this->Paginator->prev(__('previous'), array('tag' => 'li', 'model'=>$model), null, array('tag'=>'li', 'class'=>'prev off'));
                echo $this->Paginator->numbers(array('tag'=>'li', 'model'=>$model, 'separator' => false));
                echo $this->Paginator->next(__('next'), array('tag' => 'li', 'model'=>$model), null, array('tag'=>'li', 'class'=>'next off'));
            ?>
        </ul>
    </div>
    
    <?php 
        }
        echo $this->Js->writeBuffer(); 
    ?>
    
    0 讨论(0)
提交回复
热议问题