Creating a page with posts filtered by tag

Apologize if this is a basic question, but I think I’m stuck on a conceptual understanding of something related to tags. I have a blog loop on my home page, and I’d like to display the post’s tag linked to a page that contains posts with that tag.

I have the tag fields successfully set up in the panel and displaying correctly on my posts, however I can’t get the links to work right. Do I need to actually create a separate ‘tag’ page and template to link to such a filtered list of posts?

So far, in my templates (both on the home page template and on the single post template), I’m using this to display the tag and constructing the link:

<?php foreach ($page->tags()->split() as $tag): ?>
			<a href="<?php echo url('/' . url::paramsToString(['tag' => $tag])) ?>">#<?php echo html($tag) ?></a>
		<?php endforeach ?>

This results in the following output:

<a href="link_to_base_site_url">#nameoftag</a>

Any ideas on what I’m missing? Thinking maybe I need to create a specific, dedicated tag.php page and template to display these? I guess I was assuming that this would still work falling back to the default.php template, but maybe not? Thanks!

I understand I need to create a controller in order to create the filtered list of posts, as explained on this post. Do I create this controller in conjunction with a new page/template, as I mention in the OP? Thanks!

I would create a category-page + controller (or a route).

There’s a special recipe for this in the cookbook. You should check it out :+1:

1 Like

Is a category page a special kind of page? Or do you just mean create a page intended to hold the filtered list of posts (like I’m trying to communicate in the OP), and then create a corresponding controller which would house the filtered loop referenced in your link?

And thanks for the reply! :slight_smile:

Where do you display your list of posts? On the homepage? Then you can do the filtering in the homepage controller. Same as in this example, but on the home page instead of in the blog page:

1 Like

I display a list of all posts on the home page. Each post is tagged, and I want to be able to click a tag to see a filtered list of all posts with that tag.

You can see a working example of what I’m attempting to recreate here:

Then all that is left to do is add the filtering by tag in your home.php controller, like in the example I posted, at least if you use tag: sometag. If you want to use a slug for the tag, you have to do it with a route, like in the example @bart posted above.

Thanks, I don’t use a home.php controller. In fact I 'm not using any controllers yet. My site is very basic — I just use a default.php template that calls a blog_loop.php snippet for the loop. In this case would I create a default.php controller with the logic you linked to? I just tried that and it had no effect on the output of my tag links, unfortunately.

Controllers need to match the name of template they belong too, so if you home page is using home.php as its template, then the controller also needs to be named home.php.

Sounds to me like you just running the site off the default.php template that came with kirby. Is that correct?

As I said, if you want to use a url scheme like you need an additional route.

But yes, if your only template is the default.php template, then the matching controller would be a default.php controller.

My home page is just using default.php as it’s template, which is extremely basic, containing only a simple header, footer, and a blog loop which I’m storing in a snippet called blog_loop.php. Here’s what the loop looks like:

<?php foreach($posts = page('blog')->children()->listed()->flip()->paginate(10) as $post): ?>

			<a href="<?= $post->url() ?>">
				<?php foreach ($post->images() as $img): ?>
					<img src="<?= $img->url() ?>" alt="<?= $post->title()->html() ?>"></li>
				<?php endforeach ?>
		<h1><a href="<?= $post->url() ?>"><?= $post->title()->html() ?></a></h1>
			<?php foreach ($post->tags()->split() as $tag): ?>
				<a href="<?php echo url('/' . url::paramsToString(['tag' => $tag])) ?>">#<?php echo html($tag) ?></a>
			<?php endforeach ?>
<?php endforeach ?>	
<!-- END BLOG LOOP -->

<?php if ($posts->pagination()->hasPages()): ?>
	<nav class="pagination">

	<?php if ($posts->pagination()->hasNextPage()): ?>
		<a class="next" href="<?= $posts->pagination()->nextPageURL() ?>">‹ older posts</a>
	<?php endif ?>

	<?php if ($posts->pagination()->hasPrevPage()): ?>
		<a class="prev" href="<?= $posts->pagination()->prevPageURL() ?>">newer posts ›</a>
	<?php endif ?>

<?php endif ?>

Sorry, I meant another filtering example:

Note that if you set the list of posts in your template, any filtering you do in a controller will be overwritten by your template. So once you use a controller, remove your $posts definition from the template.

1 Like

Hadn’t seen that one yet, thanks! Will work through it.

See the edit I made to my last post!

1 Like