Accessing related collection data

  • I am currently outputting a collection as JSON for consumption for a JavaScript app. It's all working as expected, but now I've hit a wall with related collection content.


    I have successfully enabled selection of one of the fields via a drop-down in my primary collection. But when I try to access that on one of my pages, I don't seem to be able to. How can I access this content from the related content for use in my JSON output?


    My JSON feed

    My line 'id'             => $location['location'], is not currently able to access this data. If I print the contents of $locations on another page, the content key looks like:


    Code
    1. [location] => Array ( [0] => 3 )


    My shop/item.html


    Code
    1. <perch:content id="name" type="text" label="Shop Name" required>
    2. <perch:content id="slug" type="slug" for="name">
    3. <perch:content id="logo" type="image" label="Shop Logo" divider-after="Opening Times" required>
    4. <perch:related id="location" collection="locations" max="1" label="Select location">
    5. <perch:content id="uniqueid">
    6. </perch:related>
    7. <perch:content id="opening_times" type="textarea" label="Shop Opening Times" divider-after="Info" required>
    8. <perch:content id="info" type="textarea" label="Info" required>




  • Hi Mat,


    When you use skip-template Perch won't automatically fetch related items or categories. Instead you get their IDs. You can fetch the related items with additional perch_collection() calls.


    Alternatively you can use a Perch template to output the JSON:


    PHP
    1. header('Content-Type: application/json');
    2. perch_collection('Shops', [
    3. 'sort-order' => 'DESC',
    4. 'count' => 10,
    5. 'template' => 'shops/json.html',
    6. ]);


    And format your JSON inside the template. So you can use your perch:related tags in this case.

  • Hi Hussein,


    I thought as much. I literally been on this for an age now! I may just do as you said, as it could be a world easier to do this via a template. Out of curiosity, how would I access a specific field from the secondary collection? I've added a callback, which references the secondary collection, which pulls all of the fields through, but how would I filter for a specific field?


    Code
    1. $locations = perch_collection('Shops', [
    2. 'template' => 'shops/item_detail.html',
    3. 'skip-template' => true,
    4. 'return-html' => true,
    5. 'each' => function($item){
    6. $item['location'] = perch_collection('Locations', [
    7. ], true);
    8. return $item;
    9. },
    10. ]);

    Or would you it be tricky via this method?

  • Hi


    You can also filter inside that each function. Related fields use a dot to denote the related field parent.

  • Thank you both. I've got it working using Hussein's suggestion of using a template... much easier. Although I do want to understand how the each function works - for future situations.


    Ellimondo, what is the value field doing in that example? Where you have - 'value' => $item['field key id name'], - what would that reference? This is my shop item, for example:


    HTML
    1. <perch:content id="name" type="text" label="Shop Name" required>
    2. <perch:content id="slug" type="slug" for="name">
    3. <perch:content id="logo" type="image" label="Shop Logo" divider-after="Opening Times" required>
    4. <perch:related id="location" collection="locations" max="1" scope-parent label="Select location">
    5. <perch:content id="uniqueid">
    6. </perch:related>
    7. <perch:content id="opening_times" type="textarea" label="Shop Opening Times" divider-after="Info" required>
    8. <perch:content id="info" type="textarea" label="Info" required>


    So:



    This isn't essential, I just want to try get my head around it so I can reference this in the future. Thanks guys.

  • The each option allows you to define a PHP callback function that is applied to each item perch_collection() returns.


  • Thank you for the comprehensive write up hussein. I’m having a play in order to fully get my head around it.


    If I just add the second collection to my callback, I can see location is being populated with ALL the items from within my location collection.


    I would then assume I can filter on it to only pullout the relevant location for each relationship. But if my locations collection has no reference to the shops collection, would i not struggle to ensure I’m only getting back the locations assigned to each shop?


    apologies if I’m still looking at this incorrectly.

  • It goes the other way round. If you match the filter to the 'location' related in the 'shop' collection then the second collection call in the each loop will populate the first collection with all the results from the location collection that match the 'shop' collection related field.


    In this case all 'location' collections associated with the "shop' collection. It does the same as the template but just gives you the opportunity to manipulate the array before passing it into a template.


    This would also be useful if you want to loop through a collection listing another collection that relates back to that original collection. I've used it for looping through a seminar timetable where I had Days and Seminars. If I want to display the day with associated seminars I then need to loop through the days, and for each day output a collection of seminars that have the same related day field.


    Mine got complicated because I needed a third loop for theatres. But it works fine, apart from being able to order items on multiple fields which is not yet possible in Perch.


    You can see it in action here: https://www.wibexpo.co.uk/whats-on/seminars/. It also generates a pdf using perch_template.