Show/group parents results in search page

Hi,

I’m trying to show in the search results page, all parents of results items.

Search controller:

<?php

return function ($site) {

  $query   = get('q');
  $results = $site->index()->filterBy('template', 'items')->children()->listed()->search($query, 'title|text')->sortBy('title');


  return [
    'query'   => $query,
    'results' => $results
    

  ];

};

Search template:

 <?php if($results->count()): ?>
  <ul class="categoriesItems">
    <?php foreach ($results as $result): ?>

    <li  class="ResultCategoriesItems <?= $result->parent()->title()->slug() ?>-style">
      <span><?= $result->parent()->title() ?> </span>
      <a href="<?= $result->url() ?>">
        <?= $result->title() ?> 
      </a>


    </li>
    <?php endforeach ?>
  </ul>

  <?php else : ?>

  <div>
    <p>No post matching with: <?= html($query) ?>.</p>
    
  </div>


  <?php endif ?>

Result parent is correctly shown in the loop, but I would like to add an other one showing only parent results:

 <?php if($results->count()): ?>

<ul>
 <li><a href="parent1">parent title 1</a></li>
 <li><a href="parent2">parent title 2</a></li>
 <li><a href="parent3">parent title 3</a></li>
</ul>

<hr>

  <ul class="categoriesItems">
    <?php foreach ($results as $result): ?>

    <li  class="ResultCategoriesItems <?= $result->parent()->title()->slug() ?>-style">      
      <a href="<?= $result->url() ?>">
        <?= $result->title() ?> 
      </a>


    </li>
    <?php endforeach ?>
  </ul>

  <?php else : ?>

  <div>
    <p>No post matching with: <?= html($query) ?>.</p>
    
  </div>


  <?php endif ?>

I tried to follow some older post: Group Search Results By Parents and also with Pluck in template but no result :frowning:

Thank you for any tips.

$parents = $results->pluck('parent', null, true);
foreach($parents as $parent) {
  echo $parent->title();
}

This will only get you the parents.

If you want to group by parents, you can use the group() method with a callback. But from what you wrote above, you only want the parents, right?

1 Like

Yes excatly. Only parents needed, thank you for your help. I’m quite sur to have tried your solution before but with no result :confused: Anyway, it works perfectly now.
Grouping by parents will certainly give a more polished/finished work. I’ll try some tests and get back to you if needed :slight_smile:

Grouping the results can be achieved like this:

$groupedResults = $results->group(function($item) {
  return $item->parent();
}

Then you need two looks to render the lists (leaving out the HTML here)

<?php
foreach ($groupedResults as $parent => $resultList) {
  echo $parent->title();
  foreach ($resultList as $result) {
    echo $result->title();
  }
}

I haven’t tested how this behaves if there is no parent (i.e. if the site is the parent).

1 Like

Yes! Result is really better and more clear for the visitor! the final code to group search results with parent pages is:

search controllers:

<?php

return function ($site) {

  $query   = get('q');
  $results = $site->index()->filterBy('template', 'items')->children()->listed()->search($query, 'title|text')->sortBy('title');


  $groupedResults = $results->group(function($item) {
    return $item->parent();
  });


  return [
    'query'   => $query,
    'results' => $results,
    'groupedResults' => $groupedResults


  ];

};

and the search template:

  <?php if($results->count()): ?>
  <?php foreach ($groupedResults as $parent => $resultList) : ?>
  <h3 style="color:white"><a href="<?= page($parent)->url() ?>"><?= page($parent)->title() ?></a></h3>
  <ul class="categoriesItems itemsResults">
    <?php foreach ($resultList as $result) : ?>
    <li class="ResultCategoriesItems <?= page($parent)->title()->slug() ?>-style">
      <a href="<?= $result->url(); ?>"><?= $result->title(); ?></a>
    </li>
    <?php endforeach?>    
  </ul>
  <?php endforeach?>
  <?php else : ?>
  <div class="noResult">
    <p>No post matching with: <?= html($query) ?>.</p>
  </div>
  <?php endif ?>

Thank you Sonja.

Edit: for people who would use this code, structure folder is:

site
- all items
  - categories
    - category 1
    - category 2
    (...)

Not tested if the site is the parent.

1 Like