OctoberCMSで簡単にブログを作る（プラグイン利用の基礎）

OctoberCMSのプラグインもJS挿入するものやバックエンド（管理画面）の機能を拡張するものなどなど多岐にわたるが、ブログプラグインがフロントエンド（公開されるサイト）とバックエンドの両方に機能を追加する一般的な良い例になる。

OctoberCMSでブログ機能を使うにはOctoberCMSの作者が提供する[RainLab.Blog](http://octobercms.com/plugin/rainlab-blog)プラグインを使用すると簡単に実現できる。記事データはOctoberCMSフレームワークで設定したデータベースに保存される。

やることは、２つ

* プラグインをインストール
* テーマにブログリストとブログ記事のページを追加

プラグインのインストール方法はちょうどブログプラグインを例に「[プラグインのインストール方法３つ(GUI, Composer, 手動)](https://qiita.com/pikanji/items/cb778fa63c8a72b023e2)」で説明しているので、ここでは実際にフロントエンド（公開するウェブサイト）にブログを表示させるためページ実装を説明する。

また、ここではOctoberCMSインストールすると同梱されているテーマ "demo" を使って説明する。

## インストール確認
まず、正常にインストールされていればバックエンド（管理ページ）にブログ管理ページが表示される。

<img width="560" alt="blog_plugin.png" src="https://qiita-image-store.s3.amazonaws.com/0/138322/c3f80ebc-a7e9-e965-a708-5bef3013906c.png">


すでに、仮の投稿が入ってるが、リストページがわかりやすいようにもう一つ投稿を作っておく。
タイトル、本文に加えてSLUGが最低限必要になる。（SLUGとはURLパスパラメータのことで記事のIDとなる一意の任意の文字列を指定する。）
<img width="836" alt="Screen_Shot_2017-11-05_at_11_28_16.png" src="https://qiita-image-store.s3.amazonaws.com/0/138322/a014f861-b66b-9f22-7a58-b2a536d28d04.png">

また、Manageタブで過ぎた日時を指定してPublishedにチェックしておかないと表示されないので、やっておく。
<img width="558" alt="Screen_Shot_2017-11-05_at_14_43_47.png" src="https://qiita-image-store.s3.amazonaws.com/0/138322/3e13102a-cc96-ca45-a933-842cec032936.png">



## リストページ作成
ブログの投稿リストや投稿表示ページを実装する。ページは通常通りテーマに実装する。

ここではまず、管理画面のCMSタブからページを追加する。

<img width="752" alt="Screen_Shot_2017-11-05_at_10_57_57.png" src="https://qiita-image-store.s3.amazonaws.com/0/138322/df387088-0b19-dc7c-ce35-119ae8687c4e.png">

下図の様に最低限の４項目を入力する。内容は基本的に何でもいい。Layoutはテーマに含まれているものから選択できるが、demoテーマの場合defaultしかないので、それを選択。とりあえず、ここで"Save"をクリックして保存する。
<img width="663" alt="Screen_Shot_2017-11-05_at_11_02_59.png" src="https://qiita-image-store.s3.amazonaws.com/0/138322/ee3d3b1f-8bdb-fb86-7e30-d84ab4db2224.png">

これで、ドメイン以下の`/blog`をブラウザで開けばページが開ける。が、まだ何も表示されない。
<img width="494" alt="Screen Shot 2017-11-05 at 13.31.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/138322/9cfbaee6-d6be-6693-bdd2-4d0ff7eaf10a.png">


次にサイドメニューの "Components" から "Blog" を開き、 "Post List" コンポーネントを選択する。オレンジ色のページ編集タブにコンポーネントが追加される。
<img width="701" alt="Screen_Shot_2017-11-05_at_11_15_17.png" src="https://qiita-image-store.s3.amazonaws.com/0/138322/fca2ad40-be8e-d084-c39b-4d011ee47641.png">

これでコンポーネントが登録できたので、テンプレートからブログデータにアクセスするためのオブジェクトとしてTWIGテンプレートからアクセスすることができる。

しかし、自分で実装してみる前に、デフォルト実装を使ってみる。OctoberCMSではコンポーネントにテンプレートを提供させることができ、このPost Listコンポーネントもデフォルトのテンプレートを提供しているので、とりあえず使ってみる。

使い方は非常に簡単で、ページのマークアップセクションに下記を記述するだけ。`{% component %}`タグで、ページに登録したコンポーネントのエイリアスを引数に渡している。

```
{% component 'blogPosts' %}
```

<img width="450" alt="Screen_Shot_2017-11-05_at_13_32_53.png" src="https://qiita-image-store.s3.amazonaws.com/0/138322/8f589738-f34b-d31e-61fb-685a6f899947.png">

これだけで、ページに投稿リストが表示される。

このデフォルトテンプレートは`plugins/rainlab/blog/components/posts/default.htm`に格納されており、下記のような内容になっている。自前でテンプレートを実装する参考になる。このデフォルトテンプレートでは記事リストの他に、カテゴリ表示、パジネーションも丁寧に実装してくれている。実際、記事リストは下の方のforループ5行だけで実装されている。

```twig

{% set posts = __SELF__.posts %}

<ul class="post-list">
    {% for post in posts %}
        <li>
            <h3><a href="{{ post.url }}">{{ post.title }}</a></h3>

            <p class="info">
                Posted
                {% if post.categories.count %} in {% endif %}
                {% for category in post.categories %}
                    <a href="{{ category.url }}">{{ category.name }}</a>{% if not loop.last %}, {% endif %}
                {% endfor %}
                on {{ post.published_at|date('M d, Y') }}
            </p>

            <p class="excerpt">{{ post.summary|raw }}</p>
        </li>
    {% else %}
        <li class="no-data">{{ noPostsMessage }}</li>
    {% endfor %}
</ul>

{% if posts.lastPage > 1 %}
    <ul class="pagination">
        {% if posts.currentPage > 1 %}
            <li><a href="{{ this.page.baseFileName|page({ (pageParam): (posts.currentPage-1) }) }}">&larr; Prev</a></li>
        {% endif %}

        {% for page in 1..posts.lastPage %}
            <li class="{{ posts.currentPage == page ? 'active' : null }}">
                <a href="{{ this.page.baseFileName|page({ (pageParam): page }) }}">{{ page }}</a>
            </li>
        {% endfor %}

        {% if posts.lastPage > posts.currentPage %}
            <li><a href="{{ this.page.baseFileName|page({ (pageParam): (posts.currentPage+1) }) }}">Next &rarr;</a></li>
        {% endif %}
    </ul>
{% endif %}
```
１行目の`__SELF__`はデフォルトテンプレートでのコンポーネントオブジェクトの参照の仕方なので、自前ページのテンプレートではこれをコンポーネントのエイリアスに置き換えてやればいい。
ここの例で言うと`blogPosts.posts`でブログ記事のリストが取得できるので、リストをイテレートして記事一覧を表示することができる。

ここで作成したページは`themes/demo/pages/blog.htm`に保存されている（ここの例では"demo"テーマを使用しているため）。
中を見てみるとこれだけ。上からページの設定、コンポーネントの設定、テンプレートセクションとなっている。

```
title = "Blog"
url = "/blog/:page?"
layout = "default"
is_hidden = 0

[blogPosts]
pageNumber = "{{ :page }}"
postsPerPage = 10
noPostsMessage = "No posts found"
sortOrder = "published_at desc"
categoryPage = 404
postPage = 404
==
{% component 'blogPosts' %}
```

## 記事ページ作成
先程と同様に今度は記事本文を表示するためのページを作成する。
<img width="770" alt="Screen_Shot_2017-11-05_at_14_26_39.png" src="https://qiita-image-store.s3.amazonaws.com/0/138322/1da2832c-87bb-94d1-a2e8-98cfcc2c4deb.png">
記事ページでは、"Post"コンポーネントを追加する。コンポーネントを追加する際に左側のコンポーネントをMarkupセクションにドラッグ＆ドロップすると、デフォルトテンプレートを読み込むTWIGマークアップを自動的に挿入してくれる。

また、URLにはコロン':'で始まる`:slug`を含んでいるが、これはパスパラメータになる。例えば`localhost/blog/post/hoge`とブラウザに入れると`hoge`が`:slug`変数としてOctoberCMSが扱ってくれる。ブログ記事を作成する際に`SLUG`を指定する必要があったが、URLでこのslugを指定することで、表示する記事を指定することになる。ここでは slug = 記事ID と置き換えるとわかりやすい。

ちなみに、記事ページのデフォルトテンプレートは`plugins/rainlab/blog/components/post/default.htm`にあるので、自前でテンプレート作成する際に参考になる。

```twig

{% set post = __SELF__.post %}

<div class="content">{{ post.content_html|raw }}</div>

{% if post.featured_images.count %}
    <div class="featured-images text-center">
        {% for image in post.featured_images %}
            <p>
                <img
                    data-src="{{ image.filename }}"
                    src="{{ image.path }}"
                    alt="{{ image.description }}"
                    style="max-width: 100%" />
            </p>
        {% endfor %}
    </div>
{% endif %}

<p class="info">
    Posted
    {% if post.categories.count %} in
        {% for category in post.categories %}
            <a href="{{ category.url }}">{{ category.name }}</a>{% if not loop.last %}, {% endif %}
        {% endfor %}
    {% endif %}
    on {{ post.published_at|date('M d, Y') }}
</p>
```

## 記事リストからのリンクを修正
ブログリストの記事へのリンクが現状では404になってしまっている。これを先程作成した`/blog/post/:slug`パスに設定してやる。

ブログリストページのPost Listコンポーネントをクリックするとプロパティ設定ダイアログが表示される。そこの"Links"を開いて"Post page"でドロップダウンリストから`blog/post`を選択する。始めの`/`と後の`:slug`が省かれているが、これが記事ページのURLに指定したパスになる。

<img width="698" alt="Screen_Shot_2017-11-05_at_14_47_45.png" src="https://qiita-image-store.s3.amazonaws.com/0/138322/a365378b-5970-a262-49ce-e7d965e3789b.png">

以上で、見た目はしょぼいがとりあえずブログを実装できた。

リストページ
<img width="437" alt="Screen Shot 2017-11-05 at 14.59.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/138322/e25a283e-8489-f54d-6918-979efa1e5834.png">

記事ページ
<img width="470" alt="Screen Shot 2017-11-05 at 15.00.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/138322/10c749cd-a9cb-6a9b-a2af-992a01f92a06.png">