phproutescakephppaginationcakephp-1.3

Pagination + Routes problem in CakePHP 1.3.6


I can't paginate my results if I access them from a Routed url. These are the routes that I'm using:

// NEWS
Router::connect('/news.rss', array('controller' => 'posts', 'action' => 'index', 'ext' => 'rss'));
Router::connect('/news/*', array('controller' => 'posts', 'action' => 'index'));
Router::connect('/:lang/posts/*', array('controller' => 'posts', 'action' => 'index'));

I know that in the last route I'm not passing the :lang parameter, but if I pass it:

Router::connect('/:lang/news/*', array('controller' => 'posts', 'action' => 'index'), array('lang' => $regex['lang'], 'pass' => array('lang')));

It does not work either.

If I try to access the url /news/page:2 it will show me the results from the first page. I printed out $this->params to see if it takes the page number correctly, and, in first instance, it does:

Array
(
[lang] => ca
[named] => Array
    (
        [page] => 2
    )

[pass] => Array
    (
    )

[controller] => posts
[action] => index
[plugin] => 
[url] => Array
    (
        [ext] => html
        [url] => ca/posts/page:2
    )

[form] => Array
    (
    )
[...]
)

This part of the array (I've ommited some parts that I'll show you later) is the same if I access /news/page:2 and /posts/index/page:2, but if you take a look to this part:

Array
(
[...]
[paging] => Array
    (
        [Post] => Array
            (
                [page] => 1
                [current] => 3
                [count] => 3
                [prevPage] => 
                [nextPage] => 
                [pageCount] => 1
                [defaults] => Array
                    (
                        [limit] => 3
                        [step] => 1
                        [order] => Post.created DESC
                        [conditions] => Array
                            (
                                [Post.active] => 1
                                [Post.page] => 
                                [0] => Post.public_date <= NOW()
                            )

                    )

                [options] => Array
                    (
                        [page] => 1
                        [limit] => 3
                        [order] => Post.created DESC
                        [conditions] => Array
                            (
                                [Post.active] => 1
                                [Post.page] => 
                                [0] => Post.public_date <= NOW()
                            )

                    )

            )

    )

You can see that it doesn't take the page number correctly. But if I access from /posts/index/page:2 it takes the number well and pagination works.

If only it were pretty URLs do not bother me, but considering that the site is multilingual, I need at least that works if I access /en/posts/index/page:2 (or /en/news/page:2)...

Here is my full routes.php file:

http://pastebin.com/th4hLZNz

Anybody has an idea of what is occurring?

Thanks in advance


Solution

  • Finally I've found the solution. Actually it was easy and the biggest problem was that I did not focus it properly. I focused on the routes thinking I did something wrong, but the problem was the controller.

    Here was the problem:

    $this->paginate['conditions'] = array(
        'Post.active' => true,
        'Post.page' => $page,
        'Post.public_date <= NOW()');
    
    $this->paginate['group'] = 'Post.id';
    

    The group (in convination with the conditions) doesn't allow the paginateCount function to count the results well. So I've created my own paginateCount function on Post's Model missing the group condition:

    /**
     * This method fixes the count query 
     * when there's a GROUP BY on it
     *
     * @return integer
     */
    public function paginateCount($conditions = null, $recursive = 0, $extra = array())
    {
        $parameters = compact('conditions', 'recursive');
        $params = array();
        if (isset($extra['group']))
        {
            $params = array_merge(array(
                'fields' => array(
                    'COUNT(DISTINCT(' . $this->alias . '.' . $this->primaryKey . ')) AS `count`'
                )
            ), $parameters);
        }
        else
        {
            $params = array_merge($parameters, $extra);
        }
        return $this->find('count', $params);
    }
    

    And now it seems to work well