Using URL Links in a filter collection

Hello!
I am building a portfolio website on which I use different filters. This works fine so far. Below you can find the code snippets.

The problem I am trying to solve ist following:
Independently from the color filter, I would like to add a filter that allows to filter by the participants of a project (let’s call it cooperation). These collaboration partners are stored in the backend in a “structure” field because I want to link the names to a URL.

How can I fetch all the names of the cooperation entries, display them as a filter and filter the projects?

As far as I know the “->pluck” command does not work for a “structure” field. I thought about storing the entries in a variable as a sting (By getting them from a foreach loop). Then use this variable to pluck the data and continue – But I could not figure out how to do that in the controller… Maybe there is even a more clean / easy possibility.

Thanks for any help!

The Color-Filter in the …/templates/home.php

<div>

    <?php foreach($colors as $cl): ?>

        <?php if($cl == urldecode(param('color'))): ?>

            <a href="<?= $page->url() ?>"><?= html($cl) ?> (Exit Filter) </a>,

        <?php else : ?>

            <a href="<?= url($page->url(), ['params' => ['color' => urldecode($cl)]]) ?>"><?= html($cl) ?></a>,

        <?php endif;?>
        
    <?php endforeach ?>

</div>

The Color-Filtermechanism as a controller in …/controllers/home.php

<?php

return function ($kirby, $pages, $page, $site) {

  $allitems = $site->find('projects')->children()->listed();
  $items = $site->find('projects')->children()->listed();
  
  // add the Color filter
  if($color = param('color')) {
    //Used for multiple words categories
    $color = urldecode(param('color'));    
    $items = $items->filterBy('color', $color, ',');
  }


  //If $items is used, groups all results filters
  // fetch all Color
  $colors = $allitems->pluck('color', ',', true); 

return compact('items','allitems','color', 'colors');

};

The Blueprint of color and cooperations in …/blueprints/project.yml

  color:
    label: Color
    type: tags

  cooperation:
    label: Cooperation
    type: structure
    fields:
      name:
        label: Name
        type: text
      link:
        lanel: Webseite
        type: url

It does! E.g.

$names = $page->cooperation()->toStructure()->pluck('name', ',');

Thanks for your answer.

I already tried it because it looked the best solution but i always get an error:

Error: Call to a member function toStructure() on null

This is the controller with the two filters:

<?php

return function ($kirby, $pages, $page, $site) {

  $allitems = $site->find('projects')->children()->listed();
  $items = $site->find('projects')->children()->listed();

  // add the Color filter
  if($color = param('color')) {
    //Used for multiple words categories
    $color = urldecode(param('color'));    
    $items = $items->filterBy('color', $color, ',');
  }

 // add the Cooperation filter
 if($cooperation = param('cooperation')) {
  //Used for multiple words categories
  $cooperation = urldecode(param('cooperation'));    
  $items = $items->filterBy('cooperation', $cooperation, ',');
}

  //If $items is used, groups all results filters
  // fetch all Colors
  $colors = $allitems->pluck('color', ',', true); 
  // fetch all Cooperations
  $cooperations = $allitems->cooperation()->toStructure()->pluck('name', ',', true); 


return compact('items','allitems', 'color', 'colors', 'cooperation', 'cooperations');

};

Because you cannot call a field on a collection, you can only call it on a single page. If you want to get all items from all pages in the collection, you first have to loop through all items

Oh well that makes sense! I understand the Idea of looping through all the items but excuse my, probably super amateurish, question: How can I loop through all the projects and get all cooperation fields in my controller?

I tried this, but it only returns the values from the last listed project.

// All projects
$items = $site->find('projects')->children()->listed();

foreach($items as $coopItem ) {
$coopValue = $coopItem->cooperation()->toStructure();
}

// fetch all Cooperations
$cooperations = $coopValue->pluck('name', ','); 
$names = [];
foreach($items as $coopItem ) {
$cooperationMembersNames = $coopItem->cooperation()->toStructure()->pluck('name', ',');
  foreach($cooperationMembersNames as $name) {
    $names[] = $name;
  }
}

$names = array_unique($names);

@texnixe: Thank you so much for your help again! I finely finished the page with two filters.
One working only with Tags (Color) and one for a Structure Field (Cooperation). Some helpful stuff I also found here: Some kirby filters content options (GitHub - constantinjoly/kirby-filters: Some differents way to let the user filter categorized content with Kirby 3).

In the case someone comes along this thread here is the final code:

Tamplate PHP

<div class="filters">
    <!-- ColorFilter -->
    <div class="colorFilter">    
        <span class="filterTitle">Color:</span><br>
        <?php foreach($colors as $cl): ?>
            <?php if($cl == urldecode(param('color'))): ?>
                <a href="<?= $page->url() ?>"><?= html($cl) ?> (X) </a>,
            <?php else : ?>
                <a href="<?= url($page->url(), ['params' => ['color' => urldecode($cl)]]) ?>"><?= html($cl) ?></a>,
            <?php endif;?>
        <?php endforeach ?>
    </div>
    <!-- CooperationFilter -->
    <div class="cooperationFilter">
        <span class="filterTitle">Cooperation:</span><br>
        <?php foreach($names as $co): ?>
            <?php if($co == urldecode(param('name'))): ?>
                <a href="<?= $page->url() ?>"> <?= html($co) ?> (X) </span></a>,
            <?php else : ?>
                <a href="<?= url($page->url(), ['params' => ['name' => urldecode($co)]]) ?>"><?= html($co) ?></a>,
            <?php endif;?>
        <?php endforeach ?> 
    </div>
</div>

Controler PHP

<?php

return function ($kirby, $pages, $page, $site) {

// Get all Items
  $allitems = $site->find('projects')->children()->listed();
  $items = $site->find('projects')->children()->listed();

//   Get all Items of the cooperation 
  $names = [];
  foreach($items as $coopItem ) {
  $cooperationMembersNames = $coopItem->cooperation()->toStructure()->pluck('name', ',');
    foreach($cooperationMembersNames as $name) {
      $names[] = $name;
    }
  }

  // Color filter
  if($color = param('color')) {
    $color = urldecode(param('color'));    
    $items = $items->filterBy('color', $color, ',');
  }

  // Cooperation filter
  if($name = param('name')) {
    $name = urldecode(param('name'));    
    $items = $items->filter(function($item) use($name) {
      foreach($item->cooperation()->toStructure() as $row) {
        if ($row->name()->toString() === $name) return true; 
      }
    });
  }

  // fetch all Colors
  $colors = $allitems->pluck('color', ',', true); 
  // fetch all Cooperations
  $names = array_unique($names);

return compact('items','allitems', 'color', 'colors', 'name', 'names');

};

Blueprint YML

fields:
  color:
    label: Color
    type: tags

  cooperation:
    label: Cooperation
    type: structure
    fields:
      name:
        label: Name
        type: tags
      link:
        lanel: Webseite
        type: url