Reputation: 1145
I am trying to integrate next and prev buttons in my view page for CustomersController. In my next button, I am trying to add a link that will take to next record from the table. Same for prev that will get the previous record from the table. I tried below pagination, but when I click next, it takes me to http://localhost/path/customers/view/1?page=2
link, I want to find away that will take me to next record like this http://localhost/path/customers/view/2
// Shows the page numbers
<?= $this->Paginator->numbers() ?>
// Shows the next and previous links
<?= $this->Paginator->prev('« Previous') ?>
<?= $this->Paginator->next('Next »') ?>
// Prints X of Y, where X is current page and Y is number of pages
<?= $this->Paginator->counter() ?>
I also tried this <?= $this->Paginator->numbers(['first' => 2, 'last' => 2]); ?>
.
Upvotes: 1
Views: 986
Reputation: 3141
I found this solution, it worked fine to me, I hope it to help you:
//controller view action
public function view($id = null)
{
$ids = Cache::read('items_ids');
if (empty($ids)) {
$ids = $this->Items->find('list')->toArray();
Cache::write('items_ids', $ids);
}
/*
* $ids here must be something like this:
Array
(
............
[GS00001] => Item 1
[GS00003] => Item 2
..........
)
*/
//pr($ids);die; //this for debug
//seek to the item with id = $id
while (key($ids) !== $id) next($ids);
if($next = next($ids)){
$next = [
'id' => key($ids),
'name' => current($ids)
];
}else{
end($ids);
}
prev($ids);
if($prev = prev($ids)){
$prev = [
'id' => key($ids),
'name' => current($ids)
];
}
//pr(compact(['next','prev']));die;
/*
$next and $prev here:
If first:
Array
(
[next] => false
[prev] => Array
(
[id] => GS00264
[name] => Last Item
)
)
If last:
Array
(
[next] => Array
(
[id] => GS00003
[name] => First Item
)
[prev] => false
)
* */
$item = $this->Items->get($id, [
'contain' => ['MenuGroups', 'Orders']
]);
$this->set(compact(['item','next','prev','ids']));
$this->set('_serialize', ['item','next','prev','ids']);
}
and in the view template simply write:
<ul>
<li><?= $this->Html->link('<< ' . $prev['name'],['action'=>'view',$prev['id']]); ?></li>
<li><?= $this->Html->link($next['name'] . ' >>',['action'=>'view',$next['id']]); ?></li>
</ul>
and in Bootstrap.css case:
<nav>
<ul class="pager">
<li class="previous <?= ($prev) ? '' : 'disabled' ?>">
<?= $this->Html->link('<span aria-hidden="true">←</span> ' . $prev['name'], ['action' => 'view', $prev['id']], ['escape' => false]); ?>
</li>
<li class="next <?= ($next) ? '' : 'disabled' ?>">
<?= $this->Html->link($next['name'] . ' <span aria-hidden="true">→</span>', ['action' => 'view', $next['id']], ['escape' => false]); ?>
</li>
</ul>
</nav>
Note: you are free to use Cache
or not, but I found it useful in the case you will need this query every time, you can manually refresh the cache key in the Entity
afterSave
public function afterSave(Event $event, Item $entity, $options)
{
Cache::delete('items_ids');
}
Upvotes: 1
Reputation: 3141
We can use foreach
instead of next and prev
:
public function view($id = null)
{
$ids = Cache::read('items_ids');
if (empty($ids)) {
$ids = $this->Items->find('list')->toArray();
Cache::write('items_ids', $ids);
}
/*
* $ids here must be something like this:
Array
(
............
[GS00001] => Item 1
[GS00003] => Item 2
..........
)
*/
//pr($ids);die; //this for debug
//seek to the item with id = $id
$found = $next = $prev = false;
foreach ($ids as $key => $value) {
//pr($key);
if($found){
$next = [
'id' => $key,
'name' => $value
];
break;
}
if ($key == $id) {
$found = true;
} else {
$prev = [
'id' => $key,
'name' => $value
];
}
}
//pr(compact(['next','prev']));die;
/*
$next and $prev here:
If first:
Array
(
[next] => false
[prev] => Array
(
[id] => GS00264
[name] => Last Item
)
)
If last:
Array
(
[next] => Array
(
[id] => GS00003
[name] => First Item
)
[prev] => false
)
* */
$item = $this->Items->get($id, [
'contain' => ['MenuGroups', 'Orders']
]);
$this->set(compact(['item', 'next', 'prev', 'ids']));
$this->set('_serialize', ['item', 'next', 'prev', 'ids']);
}
Upvotes: 0