Out of the box Jigsaw doesn't provide anything to allow you to tag your posts, however, as you can see from the bottom
of my articles I have implemented a tagging system, and I will show you how I have done this.
It is all made possible by using Jigsaw Collections.
Using this feature, any collections you add to your Jigsaw site, will be available as and Illuminate\Collection variable
for your blade files, and this is what helps make it all possible
So starting by adding a basic blog collection in your config.php file
return [
'collections' => [
'blog' => [
'path' => 'posts/{date|Y/m/d}/{filename}',
'author' => 'Alan Holmes',
'tags' => []
],
],
];
This means that in any of your pages, you will have access to a $blog variable, which will be a Illuminate\Collection of
any pages you add within the _blog folder.
So something like this, will allow you to list your articles on an index page
foreach ($blog as $article)
<h2><a href="{{ $article->getPath() }}">{{ $article->title }}</a></h2>
<h3>By {{ $article->author }}</h3>
{{ $article->getContent() }}
endforeach
(With @ before foreach and endforeach)
You may have noticed the empty tags array in the blog collection, this is to ensure that every article will have the
tags array, so that we don't have to account for that later. Then all you need to do is set the tags in the front matter
section for the article
extends: _layouts.blog
title: Sample Article
tags: [php, js]
section: content
On your article page you will already have access to the tags array within the $page variable, so you can output the tags for each article:
foreach ($page->tags as $tag)
<a class="tag" href="/tag/{{ $tag }}">#{{ $tag }}</a>
endforeach
(With @ before foreach and endforeach)
All this so far as be standard functionality within Jigsaw, now we can move on to creating our /tag/* landing pages,
where we will display any articles that have been tagged with the provided tag.
Firstly, to filter the articles by a tag, we will need to add a function to the config.php.
return [
'collections' => [
'blog' => [
'path' => 'posts/{date|Y/m/d}/{filename}',
'author' => 'Alan Holmes',
'tags' => []
],
],
'getPostsForTag' => function ($page, $articles, $tag) {
return $articles->filter(function ($article) use ($tag) {
return collect($article->tags)->contains($tag);
});
},
];
The getPostsForTag is then available to call on the $page variable. By default Jigsaw passes $page through as the
first parameter, so we only need to pass the $articles and $tag when calling.
So we would call it as such
$page->getPostsForTag($blog, 'php')
This would then return any articles that contain the tag php.
To use this, I have partial for listing blog posts (so both my blog list and filtered list have the same output), so I just override the $blog
variable as such.
include('_layouts.blog.list', ['blog' => $page->getPostsForTag($blog, 'php')])
(With @ before include)
Now, for the landing page for each tag, I just create another collection in my config.php and then add a page for each tag in the _tags folder
So my config now looks like this
return [
'collections' => [
'blog' => [
'path' => 'posts/{date|Y/m/d}/{filename}',
'author' => 'Alan Holmes',
'tags' => []
],
'tags' => [
'path' => 'tag/{filename}',
],
],
'getPostsForTag' => function ($page, $articles, $tag) {
return $articles->filter(function ($article) use ($tag) {
return collect($article->tags)->contains($tag);
});
},
];
And the tag pages are all the same, and just contain
---
extends: _layouts.master
title: PHP
---
section('body')
include('_layouts.blog.list', ['blog' => $page->getPostsForTag($blog, $page->getFilename())])
endsection
(With @ before include, section and endsection)
And that is it, you are now able to tag your articles. The same principle could be used to add categories or any other type of filter you might like.