Single blog entry: How to display its tags?

Hello there,

I have a surprisingly difficult time to make Kirby show the respective tags of a single blog entry. The tag itself should, of course, link to a page with other tagged articles.

This is how the core of my blog homepage looks like:

<?php foreach($articles as $article): ?>
<div class="post">
<h1><a href="<?=$article->url()?>"><?=$article->title()?></a></h1>
<?php echo $article->text()->kirbytext() ?>
<a href="<?=$article->url()?>"><?=$article->date('d.m.Y')?>, <?=$article->time('G:i')?></a>
</div>
<?php endforeach ?>

I’m struggling with the doc, as it merely suggests to implement a cloud for all the tags. Has anyone got a solution to this? Many thanks in advance!

In your template with the single blog entry:

<?php
  $tags = $article->tags()->split(); 
?>
<ul>
<?php foreach($tags as $tag): ?>
  <!-- change link to the page that lists all articles if necessary -->
  <li><a href="<?php echo url('blog/tag:' . urlencode($tag)) ?>"><?php echo $tag ?></a></li>
<?php endforeach ?>
</ul>

In the controller of the blog or home page where you list your articles, filter by tag if the tag parameter is called:

<?php
  return function($site, $pages, $page) {

    $tag = urldecode(param('tag'));
    if($tag) {
    	$articles = page('blog')->children()->visible()->filterBy('tags', $tag,',')->sortBy('date')->flip();
    } else {
    	$articles = page('blog')->children()->visible()->sortBy('date')->flip();
    }   
   
     return compact('articles');

};

Amazing, thanks for helping me out once again! I really appreciate it!

This functionality has been broken by the latest update 2.3.0. The tags themselves are still displayed correctly, the links, however, lead to empty pages.

To be honest, the changelog overwhelms me. How am I to modify the code?

What do your links look like? The code above should not be affected by the update.

Hi, well, they look the same, with a “tag:something” suffix.

So, the links are still something like this, right, and therefore perfectly alright.

http://localhost/kirby-project/blog/tag:kirby

Have you turned on debugging in your config.php?

c::set('debug', true);

to see what sort of error you get?

Ah, it’s the obvious things I forget, thanks for the hint! Here’s what I get when I open the tag-specific page:

Fatal error: Uncaught Error: Call to a member function url() on boolean in /kirby/kirby.php:301 Stack trace: #0 /kirby/toolkit/helpers.php(270): Kirby->{closure}() #1 /kirby/kirby.php(678): call(Object(Closure), Array) #2 /index.php(16): Kirby->launch() #3 {main} thrown in /kirby/kirby.php on line 301

Is that all? That does not really tell where it is coming from …

Oh-oh. That doesn’t sound good.

Does the page display any content without the tag parameter? Do you use any page models or plugins?

Yes, it does. It displays the blog correctly, and single-article pages work as well. The only plugin I use creates the RSS feed, and there are no page models. Apart from the tag features you taught me here, there shouldn’t be anything unfamiliar.

I don’t know, is it possible that the update (via git) had a few glitches? I’m trying to re-set everything up… (Edit: Mh, didn’t work out as well.)

Some sort of caching problem, maybe?

This is the controller I use in a Kirby 2.3 starterkit and which works (but is the same as above anyway, I think)

<?php

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

  if($tag = urldecode(param('tag'))) {

    $articles = page('blog')->children()->visible()->filterBy('tags', $tag, ',')->flip();
  } else {
    $articles = page('blog')->children()->visible()->flip()->paginate(5);
  }

  $pagination = $articles->pagination();

  return compact('articles', 'pagination');
};

It’s not working I’m afraid. I reverted to Kirby 2.2.3 and it works like a charm. It has to do with something within the ’kirby’ directory.

Could you post your controller and your template, pls.?

Sure. I really appreciate you sticking around this long. Thank you.

Here’s the controller blog.php:

<?php
  return function($site, $pages, $page) {

    $tag = urldecode(param('tag'));
    if(param('tag')) {
        $articles = page('blog')->children()->visible()->filterBy('tags', $tag,',')->sortBy('date')->flip();
    } else {
        $articles = page('blog')->children()->visible()->sortBy('date')->flip();
    }   
   
     return compact('articles');

};

This is the template blog.php:

<?php snippet('header') ?>
    <?php if(param('tag')): ?>
  <div class="hash"><li><?php $tag = param('tag'); echo 'Filter&#58;  &#35;' . $tag . $articles->title() ?></li><li><a href="/">Remove</a></li></div>
  <?php endif ?>


  <?php $articles = $page->children()->visible()->flip(); if($tag = param('tag')) {$articles = $articles->filterBy('tags', $tag, ',');} $articles = $articles->paginate(5); ?>
  <?php foreach($articles as $article): ?>
        <div class="post">
      <?php if(!param('tag')): ?>
      <h1 class="post-hashtag"><?php $tags = $article->tags()->split();?><?php foreach($tags as $tag): ?><a href="<?php echo url('blog/tag:' . urlencode($tag)) ?>">&#35;<?php echo $tag ?></a> <?php endforeach ?></h1>
      <?php endif ?>
            <h1 class="post-title"><a href="<?=$article->url()?>"><?=$article->title()?></a></h1>
            <?php echo $article->first()->footnotes(false)->kirbytext() ?>
            <?php echo $article->text()->footnotes(false)->kirbytext() ?>
            <div class="read-more"><a href="<?=$article->url()?>"><?=$article->date('d.m.Y')?>, <?=$article->time('G:i')?></a>

  <?php endforeach ?>

<?php if($articles->pagination()->hasPages()): ?>
        <div class="pagination">  

          <?php if($articles->pagination()->hasNextPage()): ?>
          <a class="prev" href="<?php echo $articles->pagination()->nextPageURL() ?>">&laquo; Previous</a>
          <?php endif ?>

          <?php if($articles->pagination()->hasPrevPage()): ?>
          <a class="next" href="<?php echo $articles->pagination()->prevPageURL() ?>">Next &raquo;</a>
          </div>
          <?php endif ?>

<?php endif ?>

    </div>
    </div>

<?php snippet('footer') ?>

I tested your code and it works for me. Two things, though:

  1. You duplicate the logic from the controller in the template, which does not make sense.

  2. What is first() and footnotes()?

<?php echo $article->first()->footnotes(false)->kirbytext() ?>

Seems to be simply ignored in my setup; is that a plugin that you use? Maybe that causes the issue?

Whoops, the footnotes were from a plug-in I used to test very briefly. I have removed all references, the problem still persists in 2.3.0. Sorry for that.

first() helps me to show only the first paragraph of my entry when needed. In my panel, I have a separate form field for it. first() and text() combined are the entire blog entry.

Now, your first point sounds interesting. Am I right in assuming there are redundant parts within my template?

Yes, exactly. $articles is already returned from the controller. So no need to define $articles again in the template, in this line:

<?php $articles = $page->children()->visible()->flip(); if($tag = param('tag')) {$articles = $articles->filterBy('tags', $tag, ',');} $articles = $articles->paginate(5); ?>
  <?php foreach($articles as $article): ?>
...

Not sure about that. If I remove the relevant parts from the template, it breaks its basic functionality: creating a new page after five entries and allowing the possibility to filter the blog by tags.

The controller appears to be crucial for the pages that display only one specific tag (’blog/tag:example’). If I remove it, those pages turn blank. With Kirby 2.2.3, that is! So, could it be possible that the controller is what might cause the issue on Kirby 2.3.0?