Quite some time ago I wrote a blog post about saving CakePHP 1.x paging data in the session so that they can be available at next page visit. The basic idea was that you could store the page, sort and direction named parameters in the session and restore them back when no paging parameters were available.
When I tried applying the same technique in CakePHP 2.4, I run into a very serious obstacle and that was the fact that the Paginator::numbers() function does not anymore include the page:1 named parameter when creating the link for the first (or previous) page. This created a phenomenon that when someone visited a page without any paging parameters, it was impossible to know whether they were there because of a link to the first page or as a result of a redirect from somewhere else, in which case the session had to be checked and paging data to be restored.
The thing had been puzzling me for some days now. I tried different remedies without any luck or results until I cried for help at stackoverflow.com. It was there that Ilie Pandia shook things a bit and then I managed, thanks to his advice, to create the following component that mimics the original Cake 1.x PaginationRecallComponent by mattc found in the Bakery, from which I borrowed the name and structure.
<?php
App::uses('Component', 'Controller');
/**
* Pagination Recall CakePHP Component
* CakePHP 2.x version Copyright (c) 2014 Thanassis Bakalidis abakalidis.blogspot.com=
*
* @author thanassis
* @version 2.0
* @license MIT
*/
class PaginationRecallComponent extends Component {
const PREV_DATA_KEY = 'Pafinaion-PrevData';
public $components = array('Session');
private $_controller = NULL;
private $_previousUrl;
public function startup(Controller $controller)
{
$this->_controller = $controller;
$sessionKey = "Pagination.{$this->_controller->modelClass}.options";
// extract paging data from the request parameters
$pagingParams = $this->_extractPagingParams();
// if paging data exist write them in the session
if (!empty($pagingParams)) {
$this->Session->write( $sessionKey, $pagingParams);
return;
}
// no paging data.
// construct the previous URL
$this->_previousUrl = $this->Session->check(self::PREV_DATA_KEY)
? $this->Session->read(self::PREV_DATA_KEY)
: array(
'controller' => '',
'action' => ''
);
// and check if the current page is the same as the previous
if ($this->_previousUrl['controller'] === $this->_controller->name &&
$this->_previousUrl['action'] === $this->_controller->params['action']) {
// in this case we have a link from our own paging::numbers() function
// to move to page 1 pf the current page
return;
}
// we are comming from a different page so if we have any session data
if ($this->Session->check($sessionKey))
// then restore and use them
$this->_controller->request->params['named'] = array_merge(
$this->_controller->request->params['named'],
$this->Session->read($sessionKey)
);
}
public function shutdown(\Controller $controller)
{
// save the current controller and action for the next time
$this->Session->write(
self::PREV_DATA_KEY,
array(
'controller' => $this->_controller->name,
'action' => $this->_controller->request->params['action']
)
);
}
private function _extractPagingParams()
{
$pagingParams = $this->_controller->request->params['named'];
$vars = array('page', 'sort', 'direction');
$keys = array_keys($pagingParams);
$count = count($keys);
for ($i = 0; $i < $count; $i++)
if (!in_array($keys[$i], $vars))
unset($pagingParams[$keys[$i]]);
return $pagingParams;
}
}
0 comments:
Post a Comment