その他のTwig機能について


a-blog cms での Twig の基本的な使い方について学んできましたが、他にも便利なTwigの機能がありますので、ぜひ目を通してみてください。

Twigのドキュメント

以下一部便利な機能を紹介します。

macro(マクロ)機能

Twigには、テンプレート内で関数のように使える macro(マクロ)機能 があります。
複雑なHTML構造や繰り返し処理をひとつの関数としてまとめられるため、特に階層構造のデータを扱うときに便利です。

階層データの例

たとえば「V2_Category_Tree」モジュールは、カテゴリが入れ子になった階層構造のデータを返します。

{
  categories:
    [
      {
        id: 1,
        name: "お知らせ",
      },
      {
        id: 2,
        name: "製品",
        children:
          [
            {
              id: 3,
              name: "家庭用製品",
            },
            {
              id: 4,
              name: "業務用製品",
              children:
                [
                  {
                    id: 6,
                    name: "業務用製品のお知らせ",
                  },
                ],
            },
          ],
      },
    ]
}

for文のみで書く場合

階層をすべて表示しようとすると、階層分だけfor文をネストする必要があり、コードが深く複雑になります。

{% set tree = module('V2_Category_Tree') %}

<ul>
  {% for category in tree.categories %}
    <li>
      {{ category.name }}
      {% if category.children is not empty %}
        <ul>
          {% for child in category.children %}
            <li>
              {{ child.name }}
              {% if child.children is not empty %}
                <ul>
                  {% for child2 in child.children %}
                    <li>{{ child2.name }}</li>
                  {% endfor %}
                </ul>
              {% endif %}
            </li>
          {% endfor %}
        </ul>
      {% endif %}
    </li>
  {% endfor %}
</ul>

macroを使ってシンプルに書く

macroを使えば、階層構造の処理を再帰的に呼び出せる関数としてまとめられるため、コードがすっきりします。

{% set tree = module('V2_Category_Tree') %}

{% macro renderCategories(categories) %}
  <ul>
    {% for category in categories %}
      <li>
        {{ category.name }}
        {% if category.children is not empty %}
          {{ _self.renderCategories(category.children) }}
        {% endif %}
      </li>
    {% endfor %}
  </ul>
{% endmacro %}

{{ _self.renderCategories(tree.categories) }}
  • macroはテンプレート内で定義できる関数のような構文

  • 上記例ではrenderCategoriesというマクロを作成し、カテゴリをリスト表示。

  • 子カテゴリ(children)が存在すれば同じマクロを再帰的に呼び出し、階層の深さに制限なく対応可能。

  • 呼び出しは_self.マクロ名()で行います。

Twig記法をそのまま出力する

{{ ... }}{% ... %} など、テンプレートとして解釈されてほしくない場合は verbatim タグを使用することで、そのまま出力することができます。

たとえば、他のテンプレートエンジン(Vue.js や Angular など)と併用し、{{ }} がTwigに解釈されないようにしたい場合などに便利です。

{% verbatim %}
  {{ message }}
  {% if user %}
    Hello, {{ user }}!
  {% endif %}
{% endverbatim %}

パスの書き換え


本CMSでは、/themes/テーマ/ドキュメントルート相当として扱われます。
そのため、静的サイトをそのまま themes 内に置いても動作するよう、テンプレート内のパスを自動で書き換える機能があります。

書き換え対象

パスの書き換えには、次の2種類があります。

1. ファイル指定の書き換え

対象となるのは以下の要素や属性です。

  • {{ include('xxx') }} インクルードパス

  • img / input / script / frame / iframe 要素の src属性

  • srcset属性

  • link 要素

  • object / applet 要素

  • background属性

書き換え仕様(ファイル指定)

  1. スキーマ(http:// 等)から始まる場合 → 書き換えない

  2. / のみの場合 → 書き換えない

  3. / から始まり、ドキュメントルートから探索して見つかった場合 → 書き換えない

  4. / から始まり、a-blog cms設置ディレクトリから探索して見つかった場合 → 書き換える

  5. / から始まらない場合で、テンプレートからの相対パスとして探索して見つかった場合 → 書き換える

  6. 上記に当てはまらず、継承テーマから探索して見つかった場合 → 書き換える

2. アンカー類の書き換え

対象となるのは以下の属性です。

  • a 要素の href属性

  • form 要素の action属性

書き換え仕様(アンカー類)

  1. 空の場合 → 書き換えない

  2. スキーマ(http:// 等)から始まる場合 → 書き換えない

  3. # から始まる場合 → 書き換えない

  4. / から始まらない場合 → 書き換えない

  5. a-blog cms設置ディレクトリのパスから始まっている場合 → 書き換えない

  6. 上記に当てはまらない場合 → ブログコードからのパスに書き換える

書き換えを行わない設定

このパス書き換えは便利ですが、全ブログで共通するリンクやグローバルナビなどでは、書き換えを行いたくない場合があります。

<a href="/">HOME</a>

このコードが子ブログ内にあると、
http://ドメイン/子ブログコード/ のトップページへのリンクに書き換わってしまいます。

書き換えを防ぐ方法

アンカー類のパス書き換えを行いたくない場合は、要素に acms_no_rewrite 属性を付与します。

<a href="/" class="acms_no_rewrite">HOME</a>
  • class以外にも、独自データ属性などで指定可能です。

  • 識別子 acms_no_rewrite は、config.system.yaml で変更できます。

acms_no_rewrite: custom_identifier

Vite 連携機能


Vite(ヴィート)は、モダンなWeb開発のための高速ビルドツールです。本CMSのTwigテンプレートには、Viteでビルドしたファイルを簡単に読み込むための補助機能が組み込まれています。

使い方

a-blog cms で Vite を利用してバンドルしたファイルを読み込むためには、バックエンドとの統合で記載されている仕様に合わせて、script タグや link タグを出力する必要があります。

Twigテンプレート補助機能を使用することで、Vite の仕様に合わせてタグを出力することができるようになり、a-blog cms のテンプレート内で簡単に Vite を利用することができます。

Vite の設定

Vite の設定は vite.config.js に記述します。詳細は Vite のドキュメント を参照してください。

build.manifest を true に設定し、rollupOptions.input でエントリーポイントとなるファイルを指定します。 以下のサンプルは、themes/利用テーマ/src/js/main.js をエントリーポイントとして指定しています。

import { defineConfig } from 'vite';

export default defineConfig({
    // ...
    build: {
        manifest: true,
        rollupOptions: {
            input: {
                bundle: resolve(__dirname, 'src/js/main.js'),
            },
        },
    },
});

この設定をすることで、manifest.json にビルドされたアセットのパスが出力されるようになります。

スクリプトとスタイルの読み込み

Vite の設定が完了したら、a-blog cms のテンプレート内にスクリプトとスタイルを読み込むための記述を追加します。 head タグ内 @vite() を追加します。

<!DOCTYPE html>
<head>
  @vite('src/js/main.js')
</head>

複数のエントリーポイントを指定する場合は、配列で指定します。

<!DOCTYPE html>
<head>
  @vite(['src/js/main.js', 'src/js/main.css'])
</head>

twig テンプレートを利用している場合は vite 関数を利用できます。

<!DOCTYPE html>
<head>
  {{ vite('src/js/main.js') }}
</head>

twig で vite 関数を利用している場合に複数のエントリーポイントを指定する場合は、配列で指定します。

<!DOCTYPE html>
<head>
  {{ vite(['src/js/main.js', 'src/js/main.css']) }}
</head>

これで、Vite の開発サーバーからビルドされたアセットが読み込まれるようになります。

本番環境での利用

Vite で本番環境用ビルドしたアセットを読み込めるようにするためには、a-blog cms 設置ディレクトリにある .env ファイルを編集します。

以下のように VITE_ENVIRONMENT に production を指定します。

# Vite
VITE_ENVIRONMENT=production # development | production

これで、Vite で本番環境用ビルドしたアセットが読み込まれるようになります。

設定

@vite() の第2引数にJSON形式でオプションを指定することができます。

出力ディレクトリの設定

例えば、Vite の設定で build.outDir を bundle に設定している場合、以下のように記述します。

import { defineConfig } from 'vite';

export default defineConfig({
    // ...
    build: {
        outDir: 'bundle',
    },
});

@vite() の第2引数に出力ディレクトリを指定します。

<!DOCTYPE html>
<head>
  @vite('src/js/main.js', {
    outDir: 'bundle'
  })
</head>

twig テンプレートを利用している場合は以下のように記述します。

<!DOCTYPE html>
<head>
  {{ vite('src/js/main.js', {
    outDir: 'bundle'
  }) }}
</head>

タグの属性をカスタマイズする

タグの属性をカスタマイズすることができます。

以下の例では、エントリーポイントから出力された script タグに async 属性を追加しています。

<!DOCTYPE html>
<head>
  @vite('src/js/main.js', {
    "scriptTagAttributes": {
      "async": true
    }
  })
</head>

また、link タグの属性もカスタマイズすることができます。 以下の例では、エントリーポイントから出力された link タグに type="text/css" 属性を追加しています。

<!DOCTYPE html>
<head>
  @vite('src/styles/main.css', {
    "linkTagAttributes": {
      "type": "text/css"
    }
  })
</head>

twig テンプレートを利用している場合は、以下になります。

<!DOCTYPE html>
<head>
  {{ vite('src/js/main.js', {
    "scriptTagAttributes": {
      "async": true
    }
  }) }}
</head>
<!DOCTYPE html>
<head>
  {{ vite('src/styles/main.css', {
    "linkTagAttributes": {
      "type": "text/css"
    }
  }) }}
</head>

React の利用

React と @vitejs/plugin-react を利用する場合、既存の @vite と一緒に、追加で @viteReactRefresh を追加する必要があります。

<!DOCTYPE html>
<head>
  @viteReactRefresh
  @vite('src/js/main.jsx')
</head>

@viteReactRefresh は、React の Hot Module Replacement を有効にするためのスクリプトを出力します。

<script type="module">
  import RefreshRuntime from 'http://localhost:5173/@react-refresh'
  RefreshRuntime.injectIntoGlobalHook(window)
  window.$RefreshReg$ = () => {}
  window.$RefreshSig$ = () => (type) => type
  window.__vite_plugin_react_preamble_installed__ = true
</script>

twig テンプレートを利用している場合は、以下のように記述します。

<!DOCTYPE html>
<head>
  {{ viteReactRefresh() }}
  {{ vite('src/js/main.jsx') }}
</head>

グローバル変数

Vite 連携時の状態については、グローバル変数を用いて確認できます。

グローバル変数名

説明

VITE_ENVIRONMENT

現在の Vite の動作モードの値を出力します(development または production)です。

development の場合、Vite の開発サーバーを利用し、production の場合はビルドされたアセットを利用します。

VITE_DEV_SERVER_URL

Vite の開発サーバーの URL を出力します。

高度なカスタマイズ

環境変数を利用して、Vite の設定をカスタマイズすることができます。

a-blog cms設置ディレクトリにある .env ファイルを編集することで環境変数を設定します。

# Vite
VITE_ENVIRONMENT=production # development | production
VITE_MANIFEST_PATH=dist/.vite/manifest.json
VITE_DEV_SERVER_URL=http://localhost:5173

以下、環境変数の説明です。

変数名

説明

VITE_ENVIRONMENT

development または production を指定します。

development の場合、Vite の開発サーバーを利用し、production の場合はビルドされたアセットを利用します。

VITE_MANIFEST_PATH

manifest.json のパスを利用しているテーマディレクトリから指定します。

VITE_DEV_SERVER_URL

Vite の開発サーバーの URL を指定します。

ページルーティングの概要


本CMSでは、URLの構造ブログ・カテゴリー・エントリーの設定を元に、表示するテンプレートが自動的に決定されます。
これにより、URL設計とテンプレート設計を連動させることができ、複数ブログや多階層カテゴリーでも柔軟なページ構成が可能です。

ルーティングの流れ

  • URL解析

    • リクエストされたURLから、ブログ・カテゴリー・エントリーなどを特定します。

  • テーマの決定

    • 特定したブログのテーマ設定からテーマを確定します。

  • ページタイプの判定

    • 特定したデータ情報・URLから、トップページ、一覧ページ、エントリー詳細ページなど、ページタイプを決定します。

  • テンプレートの探索

    • ページタイプに応じたテンプレートを、確定したテーマのフォルダ内から優先順に探索します。

  • テンプレートの読み込み

    • 該当テンプレートを読み込み、モジュール・変数を解決してHTMLを生成します。

ページタイプ


テーマフォルダが確定した後は、URL情報をもとにページタイプを判定します。

ページタイプには例えば、以下のような種類があります。

  • トップページ

  • 一覧ページ

  • 詳細ページ

  • 404ページ

  • 管理ページ

ページタイプ例

トップページ

トップページは、各ブログに1ページのみ存在するページタイプです。

トップページの判定例1

ブログの設定でドメインが example.com、ブログコードが空の場合、次のURLでのみトップページと判定されます。

https://example.com

※ クエリパラメータやハッシュ(#以降)は対象外となります。

トップページの判定例2

ブログの設定でドメインが example.com、ブログコードが newsの場合、次のURLでのみトップページと判定されます。

https://example.com/news/

詳細ページ

詳細ページは、CMSのエントリー情報が一意に決まっている時のページタイプです。基本 xxxx.html で終わるURLがこれに該当します。

詳細ページの判定例1

CMSで管理している、エントリーのコード(ファイル名)と同一のURLがこれに該当します。

https://example.com/news/sample.html

※ クエリパラメータやハッシュ(#以降)は対象外となります。

詳細ページの判定例2

例外として、CMSで管理しているエントリーのコード(ファイル名)が空の場合は xxxx.html で終わらないURLになります。

news ブログ or news カテゴリーにエントリーコードが空のエントリーがある場合は、以下URLのページタイプは詳細ページになります。

https://example.com/news/

一覧ページ

一覧ページは、URL上の情報で絞り込みが行われた場合に表示されるページタイプです。
ただし、詳細ページに該当する場合は詳細ページが優先されます

一覧ページの判定例

以下のように、URLでカテゴリ・カスタムフィールド・日時・キーワード・タグなどを指定している場合、一覧ページとして扱われます。複数の条件を組み合わせた絞り込みも対象です。

カテゴリー一覧
https://example.com/news/

カスタムフィールドで検索
https://example.com/field/price/lt/3000

日時で検索
https://example.com/2025/09/

キーワードで検索
https://example.com/keyword/検索ワード/

タグで検索
https://example.com/tag/タグA/タグB/

※ クエリパラメータやハッシュ(#以降)は対象外となります。


404ページ

404ページは、URLの情報からブログ・カテゴリー・エントリーなどが特定できなかった場合かつ、固定テンプレートが存在しない場合(後述)に表示されるページタイプです。

404ページの判定例

存在しないブログ・カテゴリーを指定
https://example.com/hoge/

存在しないエントリーを指定
https://example.com/hoge.html

勘違いしやすいところとして、標準で用意されている絞り込みのURL情報でヒットがない場合には404ページタイプとはなりません

カスタムフィールドで検索でヒットしない
https://example.com/field/price/lt/99999

日時で検索でヒットしない
https://example.com/2099/12/01

キーワードで検索でヒットしない
https://example.com/keyword/hogehogehoge/

タグで検索でヒットしない
https://example.com/tag/タグAAAAAAAAAAAAA/

管理ページ

管理ページは、URLが管理ページのURLだった場合に選択されるページタイプです。基本的にはURLに /admin/xxxxx/ というパスがあると管理ページと認識されます。

管理ページの判定例

https://example.com/bid/1/admin/top/

他にもページタイプによって選択されるテンプレートはありますが、ここでの説明では省略します。

他テンプレートの例

  • サインイン画面 _member/signin.html

  • サインアップ画面 _member/signup.html

  • パスワード再発行画面 _member/reset-password.html

  • プロフィール更新画面 _member/update-profile.html

  • パスワード変更画面 _member/update-password.html

  • 退会画面 _member/withdrawal.html

  • 404エラー画面 404.html

  • 500エラー画面 500.html


ページタイプとテンプレートファイル設定

各ページタイプごとに、使用されるテンプレートファイルを設定できます。設定は 管理ページ > テーマ > テーマ設定 から行います。

テーマ設定画面で、各ページタイプ毎にテンプレートファイルを指定します。
テーマ設定画面

テーマディレクトリの選択

  • テーマディレクトリ名には、現在使用しているテーマ名が表示されます。

  • 本CMS設置ディレクトリ内の themes/ 以下にあるテーマディレクトリが、プルダウンメニューから選択できます。

template.yaml の利用

  • テーマディレクトリ内に template.yaml が存在する場合、「テンプレート設定を有効化」 することで、template.yaml に記述されたテンプレート設定が優先して読み込まれます。

  • template.yaml は、テーマを使いまわす場合に毎回テンプレートファイルを個別設定する手間を省くために利用します。

tpl_top    : index.html
tpl_index  : index.html
tpl_detail : _entry.html
tpl_404    : 404.html
tpl_admin  : admin.html
tpl_login  : _member-admin/login.html

設定の効果

このようにテーマ設定を通じて、各ページタイプごとに表示されるテンプレートファイルを柔軟に切り替えることが可能です。たとえば、以下のようにページタイプごとに異なるテンプレートを割り当てられます。

  • トップページ → _top.html

  • 一覧ページ → index.html

  • 詳細ページ → _entry.html

  • エラーページ → 404.html

  • 管理ページ → admin.html


テーマセット機能は Ver. 3.1 から導入された機能のため、Ver. 3.0 以前のバージョンを利用の方は 管理ページ > コンフィグ > テーマ設定(レガシー設定) からテーマの変更ができます。