Category Map with more than one category

Hi there,

I’m trying to use a category map as texnixe wrote several times in the forum (1, 2)

My setup is a bit different though: I’m fetching News and Projects from different pages in different categories via a controller (every news item or project can have multiple categories attached to them. This is just one of the six categories):

if($page->uid() == 'strategy') {

$projects = $pages->find('projects')->children()->visible()->filterBy('categories', 'cat_strategy', ',');
$news = $pages->find('news')->children()->visible()->filterBy('categories', 'cat_strategy', ',');
$posts = new Pages(array($projects, $news));

This works, all the items in a specific category get displayed, it doesn’t matter if it’s a news item or a project.

Then I tried to use the code bit from texnixe to show the categories and their blueprint “translation”:

<?php
  $categoryMap = c::get('categoryMap');
  echo $categoryMap[trim($page->category())];
?>

with something similar in my config:

c::set('categoryMap', array(
   'news' => 'News Article',
   'architecture' => 'Architecture',
   'photography' => 'Photography',
));

But apparently I can’t use an array for trimming. So I tried putting the categories used on an item in an array, use array_intersect, implode, but that’s just me poking around in the dark. I already learned a lot since starting with kirby a little over a year ago, but I still don’t get arrays and I don’t know how to take the array in the config and subtract the categories from the news item or project and show the translation.

Where I want to use it would be on the projects overview page where I tried something like this:

<?php $projects = page('projects')->children()->visible(); ?>
<?php foreach($projects as $project): ?>

<p class="showcase-tags">
                <?php 
                    $categoryMap = c::get('categoryMap');
                    $categories = array($project->categories()->value());
                    $categoriesFinal = array_intersect($categoryMap, $categories);
                    dump($categoryMap);
                    dump($categories);
                    dump($categoriesFinal);
                    echo implode(' | ', $categoriesFinal);
                ?>
</p>

This is the poking around in the dark part, I’m afraid.

I really hope somebody can help me here!

Cheers,
Daniel

I don’t get what you’re asking for, but using trim() icw associative arrays as you suggested should just work.

What is it you’re trying to accomplish exactly?

Thanks for your reply!

What I try to accomplish: There is an overview page of all the recent projects for example. I got to the point where everything I wanted gets displayed on that page: Project name, image and a short excerpt. Now I want to display the associated categories with the names from the labels as in the blueprint (so instead of ‘news’ I want to display ‘News Article’ from the example above). My problem is, that a project doesn’t just have one category (which worked with the code snippet by texnixe) but multiple categories and I didn’t find a solution for arrays, since I don’t really understand them (never have).

Did I just miss something?

$category = "news,architecture"; // This is the value of your $page->category() field
$categories = [
  'news' => 'News Article',
   'architecture' => 'Architecture',
   'photography' => 'Photography',
];

foreach(explode(",", $category) as $cat) {
    echo $categories[$cat] . "<br>";
}

// Output:
// News Article
// Architecture

Assuming you’re using a , as separator, the above code should output the correct values from your categoryMap array.

1 Like

That’s it, thank you so much!

<?php 
  $categoryMap = c::get('categoryMap');
  $categories = $project->categories()->value();
                
  foreach(explode(", ", $categories) as $cat) {
    echo $categoryMap[$cat] . "  |  ";
   }
?>

I thought about using a foreach loop but didn’t exactly know where to put it (or what to use exactly).
Again, thank you!

Hi, it’s me again… if you could help me again, @bvdputte, I would really appreciate it

I have that piece of code in a snippet, like in the starter kit (showcase), and I use that snippet on the home page and on the projects page.
It works fine on home, where I set a limit

 (<?php snippet('showcase', ['limit' => 4]) ?>) 

but doesn’t work on the projects page as long as I don’t set a limit there as well. I just get a “Undefined index:” for the line

echo $categoryMap[$cat] . "  |  ";

and that’s it. Which I absolutely don’t understand, since I fetch the projects in the snippet like that:

$projects = page('projects')->children()->visible(); 

which shouldn’t make any difference, if it’s on the home or projects page, right?
Can you help me with that?

Can you post the code of the snippet and how you call it in the prjects template please?

Sure, thanks for taking a look at it!

Snippet:

<?php

$projects = page('projects')->children()->visible();

if(isset($limit)) $projects = $projects->limit($limit);

?>
<h2><?= page('projects')->title()->kirbytext() ?></h2>
<div class="showcase">

  <?php foreach($projects as $project): ?>

    <div class="showcase-item">
        <div class="showcase-link">
            <?php if($image = $project->images()->sortBy('sort', 'asc')->first()): $thumb = $image->crop(600, 600); ?>
              <img src="<?= $thumb->url() ?>" alt="Thumbnail for <?= $project->title()->html() ?>" class="showcase-image" />
            <?php endif ?>
        </div>
        <div class="showcase-textbox">
            <div class="showcase-text">
                <p class="showcase-tags">
                    <?php 
                        $categoryMap = c::get('categoryMap');
                        $categories = $project->categories()->value();
                        
                        foreach(explode(", ", $categories) as $cat) {
                            echo $categoryMap[$cat] . "  |  ";
                        }
                   ?>
                </p>
                <h2><?= $project->title()->html() ?></h2>
                <p class="showcase-excerpt"><?= excerpt($project->intro(), 200) ?></p>
            </div>
             <a href="<?= $project->url() ?>">
            <div class="showcase-details">
               
                    <p>Details</p>
            </div></a>
        </div>
    </div>

  <?php endforeach ?>
</div>

And the projects template:


<?php snippet('header') ?>
<?php snippet('heroimages') ?>

  <main class="main" role="main">

    <header class="wrap distance">
      
      <div class="header-intro">
      <h1><?= ($page->alternatetitle()->isEmpty()) ? $page->title()->html() : $page->alternatetitle()->html() ?></h1>
      <div class="header-text">
        <?= $page->intro()->kirbytext() ?>
      </div>
       <?php if($page->more() != ""): 
            echo $page->more()->kirbytext();
       endif; ?>
      </div>
    </header>
      <section class="intro">
      <div class="wrap">
          <?= $page->text()->kirbytext() ?>
      </div>
    </section>
      
    <div class="wrap wide">    
      <?php snippet('showcase') ?>
    </div>

  </main>
<?php snippet('footer') ?>

I suppose you are trying to access an index of the $categoryMap array which has no elements, or you’re trying to use a value as index in the array which hasn’t been (yet?) defined in $categoryMap.

Please try:

foreach(explode(", ", $categories) as $cat) {
    if (array_key_exists($cat, $categoryMap)) {
        echo $categoryMap[$cat] . "  |  ";
    }
}
1 Like

Hey @bvdputte,

that is working like a charm, awesome!

But I don’t really get the connection - what has the limitation of displayed items to do with the categoryMap?

The categoryMap has all the same items as the checkbox values. Array_key_exists checks the $categoryMap for values coming from those checkboxes, right? Could it be that one item does not have a category, therefore it has no key to check in the categoryMap and throws an error?

Thank you again, you definitely made my day :slight_smile:

Yes, exactly :slight_smile:

1 Like