Yaml string as UID, ID in "related" pages field

Hi,

if have a “pages” field in a “casestudy” blueprint, where I can add pages with the template of “project”:

    projects:
        label: Bezug
        type: pages
        query:  site.find('projects').children.template('project')

then I have a template where I list all projects, and in that template I want to show a link to a case-study, if this project is referenced in a casestudy page.

I have a working solution, but wonder if there is a better way.

in the foreach loop over the project pages, I “look” at the referenced projects in the casestudy pages:

$caseRefIds = page('cases')->children()->listed()->template('case')->pluck('projects','id');

now with this, I have an array containing as strings the uid, but as "- projects/my-project", no matter if I use “uid” or “slug” or “id”. Since I’m in the loop over the projects, I only need to check if the current project’s uid is in this array, but because of the structured yaml syntax in the string returned in the array, I have to modify “my” current project uid to "- project" . $project->uid() and then the in_array() matches eventually.

if (in_array('- projects/' . $project->uid(),$caseRefIds)) {
   $caseLink = page('cases')->children()->listed()->findBy('projects','- projects/' . $project->uid())->url();
  }

As I said this works for now, but I wonder if I’m missing a smart helper thingie. I think the toPage()or toPages() methods maybe. But the reason I landed at this was to avoid having to loop over all the cases for every project iteration - I thought the pluck() method was smarter, but now I have the rather fickely yaml string in the array (one check failed because in the case.txt of one casestudy the related project was given as

 - >
   project/my-project

where in all other case.txt it was

 - project/my-project

What would be the “Kirby” way of doing this?

thx,
Tom

Try:

$caseRefIds = page('cases')->children()->listed()->template('case')->pluck('projects','-', true);
1 Like

Ah… thanks, :slight_smile:

this solved the first riddle. Now the correct “projects/my-project” strings are in the array.

if I find a match, then I want to return the url of that casestudy. currently I use this:

$cases = page('cases')->children()->listed();
$relatedProject = 'projects/' . $item->uid();
if (in_array($relatedProject,$caseRefIds)) {
  $caseLink = $cases->findBy('projects',$relatedProject)->url();
}

but this now fails, since the value of the “projects” field again differs. In my first solution I had

 $relatedProject = '- projects/' . $item->uid();
...

which matched in the findBy (most of the times… :wink: )
Is there a helper to check against the yaml() string in the “projects” field?

cheers,
Tom

No, it would be best to use filter() with a callback:

<?php
$caseLinks = $cases->filter(function($case) use($relatedProject) {
  return $case->projects()->toPages()->has(page($relatedProject));
});

This returns a collection (even if possibly only with one member), so

if ($caseLinks->isNotEmpty()) {
  echo $caseLinks->first()->url();
}
1 Like

Wow, thank you. This is so much shorter AND it works. cool. :100:

1 Like

I’m missing a bit of context here, but should

$relatedProject = $item->id();

instead of hardcoding the projects slug here give you the same result?

1 Like

hm, you’re right :slight_smile: seems a left over from spaghetticoding around the problem… although I’m sure that I tried it and it didn’t return the expected value, now it does. :v: