Help converting a static page to a paginated one

Hey folks,

Like many I’m new to CakePHP and am learning by doing (and by reading) but I’m struggling a bit when it comes to combining pagination with associated data. I think this is partially because:

  • I am adding it into an existing page that passes a model to the view rather than a query (and from my reading I believe pagination needs queries)
  • There are a couple of different formats / styles of coding used which muddies the water when I find examples
  • I may not be trying to implement it correctly

I’m continuing to address these things but wondered if anyone would be will to look at my code as it stands and walk me through where I’m going wrong. Note I’m looking to learn so even a quick pointer to some decent reading would be appreciated, you can assume I’ve done some cursory Googling, StackOverflow’ing and read the official docs at: Pagination - 3.10

So here’s the scenario:
I’ve got a table of collections, each collection has many collection items.
Collection items table contains a few common details including item type. There are then different tables depending on item type, Games is show in the code snippets below.
Each collection item can have one type and maps one to one to the items in its given type table.

What I’m trying to do is show the details of a collection at the top, followed by all the items it contains (with a mixture of common details and item specific details) and I’ve got this working! But a collection could have 100s of items in it so I want to paginate them.

Here is the code I think is relevant, without pagination, just ask if you need more:

CollectionsTable.php

public function initialize(array $config)
{
    parent::initialize($config);
    $this->table('collections');
    $this->displayField('name');
    $this->primaryKey('id');
    $this->belongsToMany('CollectionItems', [
        'foreignKey' => 'collection_id',
        'targetForeignKey' => 'collection_item_id',
        'joinTable' => 'collection_items_collections'
    ]);
    $this->belongsToMany('Users', [
        'foreignKey' => 'collection_id',
        'targetForeignKey' => 'user_id',
        'joinTable' => 'collections_users'
    ]);
}

CollectionsController.php

public function view($id = null)
{
     $collection = $this->Collections->get($id,
                   ['contain' => ['CollectionItems',
                    'CollectionItems.CollectableItems',
                    'CollectionItems.CollectableItems.Games',
                    'CollectionItems.CollectableItems.Consoles',
                    'Users']]);
                                                         
    $this->set('collection', $collection);
    $this->set('_serialize', ['collection']);
}

view.ctp (bits that show model usage)

...
 <h3><?= h($collection->name) ?></h3>
<table class="vertical-table">
        <tr>
            <th><?= __('Id') ?></th>
            <td><?= $this->Number->format($collection->id) ?></td>
        </tr>
        <tr>
            <th><?= __('Name') ?></th>
            <td><?= h($collection->name) ?></td>
        </tr>
        <tr>
...
   <?php if (!empty($collection->collection_items)): ?>
   <table cellpadding="0" cellspacing="0" id="collection-items">
       <tr>
           <th id="id"><?= __('Id') ?></th>
           <th id="name"><?= __('Name') ?></th>
           <th><?= __('Boxed') ?></th>
...   
<?php foreach ($collection->collection_items as $collectionItem): ?>
<tr>
    <td><?= h($collectionItem->id) ?></td>
    <td><?php if ($collectionItem->collectable_item->type == 'Game'): ?>
        <?= $this->Html->link(h($collectionItem->collectable_item->game->name), ['controller' => 'CollectionItems', 'action' => 'view', $collectionItem->id]) ?>
        <?php else : ?>

So that’s what I’ve got just now.

Rather than making this post even longer by showing what I’ve tried can anyone point me to what I should be looking at to add pagination in so I can go try it and then I’ll report back if there are further issues?

Thanks for reading folks.

A separate reply so it doesn’t look like I’ve posted quite so much!

My plan is to now:

  • Edit the CollectionsController and add in the pagination details
  • Edit the CollectionsController action View to use a query in the pagination
  • Edit the view.ctp to use a query and the PaginationHelper

Hopefully this is the right path, if it isn’t I could sure do with someone telling me so I don’t continue down the wrong path for hours!

I would move the contain to a separate query (using a finder maybe) and pass that to paginate.

Haven’t done much with finders yet but I get the impression they are just for tidying code and making reuse easier. If I can’t get the base version working I don’t see how adding that will help.

I think @raul338 meant that you can ‘manual’ search for those data, which you have got a lot (not as associated / contained) , pass them in additional variable and then use built in paginator on them.

1 Like

I meant what @jarekgol said
Somethinkg like this:

$coleccion = $this->Collections->get($id);
$items = $this->CollectionsItems->find('all', [
   'contain' => [
       'CollectionItems.CollectableItems',
       'CollectionItems.....',
   ],
]);
$items = $this->Paginator->paginate($items);
$this->set('collection', $collection);
$this->set('items', $items);

And in the replace the foreach ($collection->collection_items to simple use $items

Cheers folks, this is the approach I was thinking of adjusting to but figured the ‘contains’ way of doing things would mean I shouldn’t have to.

Will post up my revision once I get them in on the off chance they can help others.