Custom Pagination in Cake PHP

2019-03-30 18:13发布

问题:

i'm a beginner in cakePHP , and i wan't to create a custom pagination in cakePHP .

the function $paginator->numbers() ; it displays the page numbers like this :

1 | 2 | 3 | 4 | ...

by looking in the options , there is some options to change the separator, to add a class of a style css ..Etc .

what i want is to have my pagination like this :

1-20 21-40 41-60 61-80 ... >>

some one has an idea about how to code it ?

EDIT :

i've created the custom paginator helper in : app/View/Helper/ ,

and i've added my CustomPaginatorHelper to $helpers of my Controller like this :

public $helpers = array('CustomPaginator', 'Html', 'Form', 'Js');

but i got this error :

Fatal error: Class 'PaginatorHelper' not found in /Applications/MAMP/htdocs/QRCode/app/View/Helper/CustomPaginatorHelper.php on line 2

it seems that he doesn't know the PaginatorHelper !!! Where i should add my custom Paginator ??

NB : your function numbers() will display just the format of the pagination : 1-20 21-40 ...etc , but without links to the pages i think :)

EDIT 2 :

i've added App::set('PaginatorHelper','/View/Helper/'); and i don't get this error anymore. Now i try to call the numbers() method of the custom paginator like this :

$this->CustomPaginator->numbers(); 

but i get this error :

Fatal error: Call to a member function numbers() on a non-object in /Applications/MAMP/htdocs/QRCode/app/View/Codes/index.ctp on line 71

what is the source of this error ? i've tried to add my customPaginatorHelper to the $helpers variable of my Controller but i still get the same error ; any ideas ?

thanks in advance

回答1:

The key thing to know here is that there is a paginator component (used in the controller) and a paginator helper (used in the view). What you're using is the PaginatorHelper class, which handles the rendering of the elements associated with pagination.

Unfortunately, there's no way of doing what you want to achieve with the PaginatorHelper. The best approach if you want to do this would be to extend the PaginatorHelper class and override the numbers() method to return what you want.

I've taken a look at that particular method, and sadly it isn't nice - it's over 100 lines long! However, I've created a class that subclasses the PaginatorHelper and overrides the method. It's a lot of copy and paste as the original method is so long, and for that reason I've not put it directly in this answer.

You can view it here: https://gist.github.com/2037902

You also need to add CustomPaginator to the list of helpers in the controller.



回答2:

You can show answer here

Custom-Query-Pagination

You can also show another result here.

http://www.endyourif.com/custom-pagination-query-in-cakephp/



回答3:

Answer for Custom Pagination in Cake PHP

A good example of when you would need this is if the underlying DB does not support the SQL LIMIT syntax. This is true of IBM's DB2. You can still use the CakePHP pagination by adding the custom query to the model.

Should you need to create custom queries to generate the data you want to paginate, you can override the paginate() and paginateCount() model methods used by the pagination controller logic. You also need to override the core paginateCount(), this method expects the same arguments as Model::find('count'). The example below uses some Postgres-specifc features, so please adjust accordingly depending on what database you are using.

Thanks see if this helps



回答4:

I found even an easier way of achieving the same thing. You will notice PaginationHelper extends AppHelper. So, if you copy any functions from the PaginatorHelper to the AppHelper calls and call it from the PaginationHelper, it will behave the same way and without any erros.

Usage

$numbers_config = array(
"before" => null,
"after" => null,
"separator" => "",
"tag" => "li"
);
echo $this->Paginator->customNumbers($numbers_config);

Code

// /app/View/AppHelper.php

App::uses('Helper', 'View');

class AppHelper extends Helper {

    public function customNumbers($options = array()) {
        if ($options === true) {
            $options = array(
                'before' => ' | ', 'after' => ' | ', 'first' => 'first', 'last' => 'last'
            );
        }

        $defaults = array(
            'tag' => 'span', 'before' => null, 'after' => null, 'model' => $this->defaultModel(), 'class' => null,
            'modulus' => '8', 'separator' => ' | ', 'first' => null, 'last' => null, 'ellipsis' => '...',
            'currentClass' => 'current', 'currentTag' => null
        );
        $options += $defaults;

        $params = (array)$this->params($options['model']) + array('page' => 1);
        unset($options['model']);

        if ($params['pageCount'] <= 1) {
            return false;
        }

        extract($options);
        unset($options['tag'], $options['before'], $options['after'], $options['model'],
            $options['modulus'], $options['separator'], $options['first'], $options['last'],
            $options['ellipsis'], $options['class'], $options['currentClass'], $options['currentTag']
        );

        $out = '';

        if ($modulus && $params['pageCount'] > $modulus) {
            $half = intval($modulus / 2);
            $end = $params['page'] + $half;

            if ($end > $params['pageCount']) {
                $end = $params['pageCount'];
            }
            $start = $params['page'] - ($modulus - ($end - $params['page']));
            if ($start <= 1) {
                $start = 1;
                $end = $params['page'] + ($modulus - $params['page']) + 1;
            }

            if ($first && $start > 1) {
                $offset = ($start <= (int)$first) ? $start - 1 : $first;
                if ($offset < $start - 1) {
                    $out .= $this->first($offset, compact('tag', 'separator', 'ellipsis', 'class'));
                } else {
                    $out .= $this->first($offset, compact('tag', 'separator', 'class', 'ellipsis') + array('after' => $separator));
                }
            }

            $out .= $before;

            for ($i = $start; $i < $params['page']; $i++) {
                $out .= $this->Html->tag($tag, $this->link($i, array('page' => $i), $options), compact('class')) . $separator;
            }

            if ($class) {
                $currentClass .= ' ' . $class;
            }
            if ($currentTag) {
                $out .= $this->Html->tag($tag, $this->Html->tag($currentTag, $params['page']), array('class' => $currentClass));
            } else {
                $out .= $this->Html->tag($tag, "<a href='#'>".$params['page']."</a>", array('class' => $currentClass));
            }
            if ($i != $params['pageCount']) {
                $out .= $separator;
            }

            $start = $params['page'] + 1;
            for ($i = $start; $i < $end; $i++) {
                $out .= $this->Html->tag($tag, $this->link($i, array('page' => $i), $options), compact('class')) . $separator;
            }

            if ($end != $params['page']) {
                $out .= $this->Html->tag($tag, $this->link($i, array('page' => $end), $options), compact('class'));
            }

            $out .= $after;

            if ($last && $end < $params['pageCount']) {
                $offset = ($params['pageCount'] < $end + (int)$last) ? $params['pageCount'] - $end : $last;
                if ($offset <= $last && $params['pageCount'] - $end > $offset) {
                    $out .= $this->last($offset, compact('tag', 'separator', 'ellipsis', 'class'));
                } else {
                    $out .= $this->last($offset, compact('tag', 'separator', 'class', 'ellipsis') + array('before' => $separator));
                }
            }

        } else {
            $out .= $before;

            for ($i = 1; $i <= $params['pageCount']; $i++) {
                if ($i == $params['page']) {
                    if ($class) {
                        $currentClass .= ' ' . $class;
                    }
                    if ($currentTag) {
                        $out .= $this->Html->tag($tag, $this->Html->tag($currentTag, $i), array('class' => $currentClass));
                    } else {
                        $out .= $this->Html->tag($tag, $i, array('class' => $currentClass));
                    }
                } else {
                    $out .= $this->Html->tag($tag, $this->link($i, array('page' => $i), $options), compact('class'));
                }
                if ($i != $params['pageCount']) {
                    $out .= $separator;
                }
            }

            $out .= $after;
        }

        return $out;
    }

}


回答5:

I found even simpler solution, No Custom code needed and will be in a CakePHP's way of doing it, might not work in CakePHP 2.0 below versions cause I checked in 2.5...

For Paginators number() method you can always override its default array() which is like:

$defaults = array(
            'tag' => 'span', 'before' => null, 'after' => null, 'model' => $this->defaultModel(), 'class' => null,
            'modulus' => '8', 'separator' => ' | ', 'first' => null, 'last' => null, 'ellipsis' => '...',
            'currentClass' => 'current', 'currentTag' => null
);

now we can override these defaults anytime we want just use these attributes in your options array() for example in your case:

    $this->Paginator->numbers(
                              array(
                                'separator' => ' - ',
                                'after' => '',
                                'before' => ''
    ));