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.