Collections

Jigsaw provides powerful features for working with groups of related pages, or collections. Collections give you the ability to access your content at an aggregate level, enabling you to easily add near-dynamic features like menus, pagination, categories, and tags to your static site.

Collections can be used to generate pages of related content—for example, blog posts or articles that are sorted by date, with an index page displaying summaries of the five most recent posts—or for embedding related blocks of content within a page, for content like staff bios, product descriptions, or a portfolio of projects.

Defining a Collection

To define a collection, add an array named collections to config.php. Each collection should be indicated by the name of the collection (typically, plural), followed by an array of settings. For example:

config.php

1<?php
2 
3return [
4 'company' => 'Tighten',
5 'contact_email' => 'support@tighten.co',
6 'collections' => [
7 'people' => [
8 'path' => 'people',
9 'sort' => 'last_name',
10 ],
11 'posts' => [
12 'path' => 'blog/{date|Y-m-d}/{filename}',
13 'author' => 'Tighten',
14 ],
15 ],
16];

Jigsaw will look for collection items in a directory with the same name as your collection, preceded by an underscore: in this example, _people and _posts. Collection items can be Markdown or Blade files, or even Blade/Markdown hybrid files.

source
_assets
_layouts
master.blade.php
post.blade.php
_people
george-michael-bluth.blade.php
j-walter-weatherman.blade.php
steve-holt.blade.php
_posts
1-my-first-post.md
2-my-second-post.md
3-my-third-post.md
assets
about-us.blade.php
blog.blade.php
index.blade.php
tasks
vendor
bootstrap.php
composer.json
composer.lock
config.php
package.json
webpack.mix.js

In config.php, the array where you define your collection can contain path and sort settings for the collection, as well as variables and helper functions. None of these elements are required, however; if omitted, default path and sort settings will be used. In fact, for the simplest configuration using default settings and no variables or functions, you can define a collection with simply its name:

config.php

1<?php
2 
3return [
4 'collections' => [ 'posts' ],
5];

Generating Collection Pages

If you'd like to generate an individual page for each of your collection items—for example, a page for each blog post—specify a parent template file in the extends key of the YAML front matter, or with the @extends directive in a Blade file, just as you would with a regular Jigsaw page. For example:

my-first-post.md

1---
2extends: _layouts.post
3title: My First Blog Post
4author: Keith Damiani
5date: 2017-03-23
6section: content
7---
8 
9This post is *profoundly* interesting.

_layouts/post.blade.php

1@extends('_layouts.master')
2 
3@section('body')
4 <h1>{{ $page->title }}</h1>
5 <p>By {{ $page->author }}{{ date('F j, Y', $page->date) }}</p>
6 
7 @yield('content')
8@endsection

Accessing Collection Items

In any Blade template, you have access to each of your collections using a variable with the collection's name. This variable references an object that contains all the elements in your collection, and can be iterated over to access individual collection items. The collection variable also behaves as if it were an Illuminate Collection in Laravel, meaning you have access to all of Laravel's standard collection methods like count(), filter(), and where().

For example, to create a list of the titles for all your blog posts, you can iterate over the $posts object in a Blade @foreach loop, and display the title property that you defined in the YAML front matter of each post:

posts.blade.php

1<p>Total of {{ $posts->count() }} posts</p>
2 
3<ul>
4@foreach ($posts as $post)
5 <li>{{ $post->title }}</li>
6@endforeach
7</ul>

For example, assuming that all posts have on their YAML front matter the property author, to filter all posts from a particular author, you can filter the collection of $posts and generate a new collection:

author_posts.blade.php

1@php
2 $authorPosts = $posts->filter(function ($value, $key) use ($page) {
3 return $value->author == $page->author;
4 });
5@endphp
6 
7@if ($authorPosts->count() > 0)
8 <ul>
9 @foreach ($authorPosts as $post)
10 <li>{{ $post->title }}</li>
11 @endforeach
12 </ul>
13@endif

Collection Metadata

In addition to the metadata available for every page, such as getPath(), getUrl(), and getFilename(), collection items have access to a few additional functions:

  • getContent() returns the main content of the collection item, i.e. the body of the Markdown file (currently, getContent() is available for Markdown files only)
  • getCollection() returns the name of the collection
  • getPrevious() and getNext() give you the adjacent items in the collection, based on the collection's default sort order
  • getFirst() returns the first item of a collection (as does the Laravel collection method first())
  • getLast() returns the last item of a collection (as does the Laravel collection method last())

_layouts/post.blade.php

1@extends('_layouts.master')
2 
3@section('body')
4 <h1>{{ $page->title }}</h1>
5 
6 @yield('content')
7 
8 @if ($page->getNext())
9 <p>Read my next post:
10 <a href="{{ $page->getNext()->getPath() }}">{{ $page->getNext()->title }}</a>
11 </p>
12 @endif
13@endsection