Forum

Thread tagged as: Question, Runway

Suggestions - Code improvement for next/prev collection links

Hi guys,

Just looking to see if anyone has any insight into some improvements for something I've adapted from Shane Lenzen, here in the Perch community. Due to the way I am building my page I needed to get the values directly into a Perch system variable for use in the template rather than a function in the page. What I have is 100% working but I an keen to make it as efficient as possible and learn in the process. It may be that this is actually fine, and there isn't a better way but as you will see - I start by calling $result to store my collection (this is needed so that I can use the $result to find the next and previous items in the collection), but I have to end the whole thing calling $result again in order to get the collection to inherit the system variables that get set. Is there a better way of ordering things so I don't need to call $result twice?

//team output
    if (perch_get('s')){
        //detail view

        // get current item
        $result = perch_collection('Our Team',[
            'filter'=>'slug',
            'match'=>'eq',
            'value'=>perch_get('s'),
            'skip-template'=>true,
            'return-html'=>true
        ]);

        // get previous item
        $prev = perch_collection('Our Team', array(
            'template' => 'coaches_prev.html',
            'filter' => '_order',
            'match' => 'lt',
            'value' => $result[0]['_sortvalue'],
            'sort' => '_order',
            'sort-order' => 'DESC',
            'count' => 1,
            'skip-template' => true,
            'return-html' => true
        ));
        // if there is no previous item, loop to last item
        if (empty(array_filter($prev))) {
            $prev = perch_collection('Our Team', array(
                'template' => 'coaches_prev.html',
                'sort' => '_order',
                'sort-order' => 'DESC',
                'count' => 1,
                'skip-template' => true,
                'return-html' => true
            ));
            //update var
            PerchSystem::set_var('prev_coach', $prev['html']);
        } 
        // previous item link
        else {
            //set var
            PerchSystem::set_var('prev_coach', $prev['html']);
        }

        // get next item
        $next = perch_collection('Our Team', array(
            'template' => 'coaches_next.html',
            'filter' => '_order',
            'match' => 'gt',
            'value' => $result[0]['_sortvalue'],
            'sort' => '_order',
            'sort-order' => 'ASC',
            'count' => 1,
            'skip-template' => true,
            'return-html' => true
        ));
        // if no next item, loop to first item
        if (empty(array_filter($next))) {
            $next = perch_collection('Our Team', array(
            'template' => 'coaches_next.html',
            'sort' => '_order',
            'sort-order' => 'ASC',
            'count' => 1,
            'skip-template' => true,
            'return-html' => true
            ));
            //update var
            PerchSystem::set_var('next_coach', $next['html']);
        } 
        // next item link
        else {
            //set var
            PerchSystem::set_var('next_coach', $next['html']);
        }

        $result = perch_collection('Our Team',[
            'filter'=>'slug',
            'match'=>'eq',
            'value'=>perch_get('s'),
            'skip-template'=>true,
            'return-html'=>true
        ]);

        // output item in detail view
        echo $result['html'];

    } else{
        //list view
        perch_collection('Our Team', [
            'template' => 'coaches_listing.html',
            'sort'     => 'coach_name',
        ]);
    }
Mathew Doidge

Mathew Doidge 2 points

  • 4 years ago

I got the idea from this doc, so I think it's fundamentally sound. It looks like you're calling the current item twice though. You have this both at the top and near the bottom:

$result = perch_collection('Our Team',[
'filter'=>'slug',
'match'=>'eq',
'value'=>perch_get('s'),
'skip-template'=>true,
'return-html'=>true
]);

You've already set $result at the top so you can get rid of the second one.

Hi Shane,

I need the second call to $result in order for the collection to have access to the PerchSystem::set_var above it - they need to appear before my call.

Ohhh right, of course. Anyway, 4 trips (or 6 for first/last) to the DB doesn't sound too bad IMO.

Yeh, I can't work out a better way, and it works, so for now at least, I'm happy. I was trying to see if I could make the db call and store in a session variable but that didn't pan out.

Drew McLellan

Drew McLellan 2638 points
Perch Support

Another way would be to output string placeholders in your main template, and then just do a basic str_replace() with the results when you have them.

Thanks Drew, that works really well. I ended up with:

$result = str_replace("%next%", $next['html'], $result);
$result = str_replace("%prev%", $prev['html'], $result);
echo $result['html'];
Duncan Revell

Duncan Revell 78 points
Registered Developer

Mat, bit late to this, but another alternative is:

// get current item 
$result = perch_collection('Our Team',[ 
'filter'=>'slug', 
'match'=>'eq', 
'value'=>perch_get('s'), 
'skip-template'=>true, 
 ]);

Do your set_var stuff here

perch_template('path_to_template.html', $result);

Just another way to split the template processing part out into its own call.

Hey Duncan, thanks for sharing this. I've never seen perch_template, in all honesty! (though I have a memory like a wooden spoon). Good to know, gained a lot from this!