mk97
mk97

Reputation: 274

Paginate related data in hasMany relationship

I'm having some trouble trying to paginate related data in a hasMany relationship

I have two models - Collection and Item Collection hasMany Item Item belongsTo Collection

In the Collection view.ctp it shows the collection details for the ID being passed along with related data of the Items. It receives this data from a find "first" call.

$this->set('collection', $this->Collection->find('first', $options));

With the resulting array looking like:

array(
    'Collection' => array(
        'id' => '4fc923f5-0a58-453f-9507-0c0c86106d80',
        'name' => '<collection_name>'
    ),

    'Item' => array(
        (int) 0 => array(
            'id' => '4fc92403-000c-4ed2-9dae-0c0c86106d80',
            'name' => 'Item1'
        ),
        (int) 1 => array(
            'id' => '4fc9241b-35ec-4810-b511-0c0c86106d80',
            'name' => 'Item2'
        ),
        (int) 2 => array(
            'id' => '4fc96e5d-ad74-4c05-a9da-0c0c86106d80',
            'name' => 'Item3'
        ),
        (int) 3 => array(
            'id' => '4fc96e64-a110-4036-bea2-0c0c86106d80',
            'name' => 'Item4'
        )
    )

Now I can get the same results from this paginate call except there is the added 0 index

$this->set('items', $this->paginate('Collection', array('Collection.id'=>$id)));

array(
    (int) 0 => array(

        'Collection' => array(
            'id' => '4fc923f5-0a58-453f-9507-0c0c86106d80',
            'name' => '<collection_name>'
        ),

        'Item' => array(
            (int) 0 => array(
                'id' => '4fc92403-000c-4ed2-9dae-0c0c86106d80',
                'name' => 'Item1'
            ),
            (int) 1 => array(
                'id' => '4fc9241b-35ec-4810-b511-0c0c86106d80',
                'name' => 'Item2'
            ),
            (int) 2 => array(
                'id' => '4fc96e5d-ad74-4c05-a9da-0c0c86106d80',
                'name' => 'Item3'
            ),
            (int) 3 => array(
                'id' => '4fc96e64-a110-4036-bea2-0c0c86106d80',
                'name' => 'Item4'
            )
      )
  )
);

I can perform an array_shift on the array returned but then the pagination doesn't work. I can try creating a custom paginate function for this but wanted to know if there's a simplier way to do this with the standard paginate I'm using since it has the data I want, just extra first array parent element [0].

Thanks in advance for any suggestions.

Upvotes: 2

Views: 3100

Answers (1)

Andrew Senner
Andrew Senner

Reputation: 2509

<?php

// Don't pull in child data, we'll fetch that manually.
$this->Collection->contain(); // Assuming you have this behavior.

// Get the collection.
$collection = $this->Collection->find('first', $options);

// Conditions
$this->paginate['Item'] = array(
    'conditions' => array(
        'Item.collection_id' => $collection['Collection']['id'];
    )
);

// Get the items
$items = $this->paginate('Item');

// Return to original child model structure.
array_walk($items, function(&$v) { // Anonymous functions requires PHP 5.3
    $v = $v['Item'];
});

// Add it to the collection array.
$collection['Item'] = $items;

?>

That's the way I implement pagination on child models. Give it a shot, might work for you too.

-A

Upvotes: 2

Related Questions