第6回:一覧ページを整える


この章でやること

  • news/index.twig に V2_Entry_Summary モジュールを実装する

  • サムネイル画像・サマリー・タグを出力する

  • ページャー(「もっと見る」ボタン)を実装する

  • モジュールIDと画像フィールドの紐付けを確認する

この章で3つのメインテンプレート(トップ・詳細・一覧)がすべて揃い、サイトとしての基本的な動作が完成します。


1. テンプレートを準備する

現在、/news/ にアクセスすると、静的HTMLの news/index.html が表示されているか、または一覧ページ用のテンプレートが存在しないため404になるかページが表示されない場合があります。一覧ページをCMS化するには、テンプレートファイル news/index.twig が必要です。

既存の静的ページをひな形にしてテンプレートを作ります。

news/index.html をリネームして news/index.twig を作成してください。

/themes/sample/
├── _top.twig
├── news/
│   ├── index.twig   ← 追加
│   └── _entry.twig
├── service/
├── contact/
├── css/
└── images/

この状態で https://ablogcms-tutorial.ddev.site/news/ にアクセスすると、お知らせ一覧ページが表示されます。まだCMS化されていないため、静的HTMLの内容がそのまま表示されています。ここからモジュールIDの設定とテンプレートの実装を進めていきます。


2. 対象のファイルを確認する

news/index.twig を開くと、見出しの下にお知らせを繰り返し表示している部分があります。

<div class="border-b border-gray-200 pb-8 mb-12">
  <h1 class="text-3xl font-bold ...">News</h1>
  <p class="mt-4 text-lg text-gray-600">最新情報や季節限定のメニューなどをお届けします。</p>
</div>
<ul class="space-y-8">
  <li>
    ...(今回の対象)
  </li>
</ul>

この <ul><li> の繰り返し部分を V2_Entry_Summary モジュールに置き換えます。モジュールIDは news_index とします。


3. 管理画面でモジュールIDを先に作成する

今回はテンプレートの実装より先に管理画面の設定を行います。一覧ページで画像を表示するための「メインイメージ」設定は、管理画面側で先に指定しておく必要があるためです。

管理画面に移動し、モジュールID news_index を作成します。

条件設定

項目

設定値

モジュール

V2サマリー(V2_Entry_Summary)

モジュールID

news_index

名前

お知らせ一覧用

URLコンテキスト

チェックを入れる(/news/ のURL情報から自動的に「お知らせ」カテゴリーを取得)

ページ番号

チェックを入れる(2ページ目以降のURLを正しく処理するために必須)


URLコンテキストとは

トップページ用の news_top では「カテゴリーIDの参照」でお知らせカテゴリーを直接指定しました。 一覧ページでは「URLコンテキスト」を有効化します。「URLコンテキスト」有効化することで、/news/ というURLパスから a-blog cms が自動的に「お知らせ」カテゴリーを判定するため、カテゴリーIDを手動で指定する必要がありません。

ページ番号のチェックは忘れがちですが必須です。2ページ目以降のURL(/news/page/2/ など)の情報もモジュールIDに渡すことで、正しいページングが機能します。

URLコンテキスト


表示設定

項目

設定値

表示件数

3

表示順

日付(降順)

メインイメージ対象

カスタムフィールドにチェックを入れて entry_main_image を指定

「メインイメージ対象」を設定することで、カスタムフィールドで登録した画像を entry.mainImage.path で取得できるようになります。

表示件数を3、表示順を日付(降順)に設定している管理画面
メインイメージ対象をカスタムフィールドに設定している管理画面

4. 繰り返し表示される記事をTwig化する

管理画面の設定が完了したら、手順1で作成した news/index.twig のテンプレート実装に進みます。

まずモジュール呼び出しとループの骨格を書きます。

{% set entrySummary = module('V2_Entry_Summary', 'news_index') %}
<ul class="space-y-8">
  {{ include('/admin/module/setting.twig', { moduleInfo: entrySummary.moduleInfo }) }}
  {% for entry in entrySummary.items %}
    <li>
      ...(繰り返し表示される記事)
    </li>
  {% endfor %}
</ul>
...(もっと見るリンク)

{{ include('/admin/module/setting.twig', { moduleInfo: entrySummary.moduleInfo }) }} を追加することで、ログイン中の管理者が一覧表示部分にホバーすると「編集」リンクが表示され、閲覧画面から直接モジュールID(news_index)の設定を編集できるようになります。

次に <li> の中身を実装します。変換前の静的HTMLと変換後のTwig版を対比して見ていきましょう。

変換前(静的HTML)

<li>
  <a href="20250807.html" class="group block p-6 sm:p-8 rounded-lg ...">
    <article class="grid md:grid-cols-3 gap-8 items-start">
      <div class="md:col-span-1 overflow-hidden rounded-lg">
        <img src="/images/news_tomato_pasta.jpg" alt="季節のサラダ" class="...">
      </div>
      <div class="md:col-span-2">
        <p class="text-sm text-gray-500">
          <time datetime="2025-08-07">2025年8月7日</time>
        </p>
        <h2 class="...">新しい季節限定メニューが登場しました</h2>
        <p class="mt-3 text-gray-600 leading-relaxed">
          太陽の恵みをたっぷりと受けた新鮮な夏野菜と…
        </p>
        <div class="mt-4 flex flex-wrap items-center gap-x-4 gap-y-2">
          <span class="bg-sky-100 ...">新商品</span>
          <span class="text-sm text-gray-500">#季節限定</span>
          <span class="text-sm text-gray-500">#夏メニュー</span>
        </div>
        <p class="...">続きを読む →</p>
      </div>
    </article>
  </a>
</li>

変換後(Twig版)

<li>
    <a href="{{ entry.url }}" class="group block p-6 sm:p-8 rounded-lg hover:bg-gray-50 transition-colors duration-300">
        <article class="grid md:grid-cols-3 gap-8 items-start">
            <div class="md:col-span-1 overflow-hidden rounded-lg">
                {% if entry.mainImage and entry.mainImage.path %}
                  <img
                    src="{{ entry.mainImage.path | resizeImg(600) }}"
                    alt="{{ entry.mainImage.alt }}"
                    class="w-full h-56 object-cover shadow-md ..."
                    width="{{ entry.mainImage.width }}"
                    height="{{ entry.mainImage.height }}"
                    loading="lazy"
                    decoding="async">
                {% endif %}
            </div>
            <div class="md:col-span-2">
                <p class="text-sm text-gray-500"><time datetime="{{ entry.date | date('Y-m-d') }}">{{ entry.date | date('Y年m月d日') }}</time></p>
                <h2 class="mt-2 text-xl font-bold text-gray-900 transition-colors group-hover:text-sky-600">
                    {{ entry.title }}
                </h2>
                <p class="mt-3 text-gray-600 leading-relaxed">
                    {{ entry.summary | mb_trim(200, '...') }}
                </p>
                <div class="mt-4 flex flex-wrap items-center gap-x-4 gap-y-2">
                    {% if entry.category.items is not empty %}
                        <span class="bg-sky-100 text-sky-800 text-xs font-semibold px-2.5 py-0.5 rounded-full">{{ entry.category.items[0].name }}</span>
                    {% endif %}
                    {% for tag in entry.tags %}
                        <span class="text-sm text-gray-500">#{{ tag.name }}</span>
                    {% endfor %}
                </div>
                <p class="mt-4 inline-block font-semibold text-sky-600 transition-transform duration-300 group-hover:translate-x-1">
                    続きを読む &rarr;
                </p>
            </div>
        </article>
    </a>
</li>

置き換えポイント解説

画像の条件出力

{% if entry.mainImage and entry.mainImage.path %}
  <img
    src="{{ entry.mainImage.path | resizeImg(600) }}"
    alt="{{ entry.mainImage.alt }}"
    class="w-full h-56 object-cover shadow-md ..."
    width="{{ entry.mainImage.width }}"
    height="{{ entry.mainImage.height }}"
    loading="lazy"
    decoding="async">
{% endif %}

V2モジュールでは画像を entry.mainImage オブジェクトで受け取ります。pathaltwidthheight を個別に取得できるため、適切な alt テキストや実際の画像サイズも出力できます。

また、a-blog cms 独自の resizeImg フィルターを利用して画像をリサイズしています。

サマリーの文字数制限

{{ entry.summary | mb_trim(200, '...') }}

a-blog cms 独自の mb_trim フィルターでサマリーを200文字で切り詰め、末尾に「...」を付けます。

a-blog cms の Twig テンプレートでは「校正オプション」がそのままTwig フィルターとして利用できます。 他にも多くのフィルターがありますので、詳しくは公式ドキュメントの 「校正オプション」 をご覧ください。

ただし、Twig 標準のフィルターと名前が重複するものについてはプレフィックス acms_ を付与して指定する必要があります。


5. ページネーションを実装する

3件ごとにページが切り替わる「もっと見る」ボタンを実装します。V2モジュールではページネーション情報はモジュールデータの pagination プロパティに格納されています。

変換前(静的HTML)

<div class="mt-16 text-center">
  <a href="page2.html" class="...">もっと見る</a>
</div>

変換後(Twig版)

{% if entrySummary.pagination.nextPage %}
  <div class="mt-16 text-center">
    <a href="{{ entrySummary.pagination.nextPage.url }}" class="inline-flex items-center rounded-md border border-transparent bg-sky-600 px-6 py-3 text-base font-medium text-white shadow-sm hover:bg-sky-700 focus:outline-none focus:ring-2 focus:ring-sky-500 focus:ring-offset-2">
      もっと見る
    </a>
  </div>
{% endif %}

entrySummary.pagination.nextPage が存在する(次のページがある)ときだけボタンを表示します。最終ページに達すると pagination.nextPage が空になり、ボタン全体が非表示になります。

https://ablogcms-tutorial.ddev.site/news/ にアクセスして、最新の3件が表示され、「もっと見る」をクリックすると2ページ目以降も正しく表示されることを確認してください。

ページネーションが実装できたら news/page2.html は不要なので削除してください。


6. カスタムフィールドと画像フィールドの紐付けを確認する

第4章で field.html に画像フィールド(entry_main_image)を定義しました。一覧ページでその画像を表示するには、モジュールID側でも「どのフィールドをメインイメージとして使うか」を指定する必要があります。

手順3で作成した news_index のモジュールID設定を開き、「表示設定」タブで以下を確認してください。

項目

設定値

メインイメージ対象

カスタムフィールドにチェックが入っているか確認

この設定があることで、テンプレート内で entry.mainImage.path として画像を取得できます。第4章で記事投稿時に画像をアップロード済みであれば、この時点で一覧ページに画像が表示されます。

7. 管理ボックスと管理用アセットを設置する

一覧ページにも管理ボックスを設置し、ログイン状態で「新規投稿」「管理画面へ移動」などの操作ができるようにします。また、管理UIが正しいデザインで表示されるよう、管理用アセットを読み込みます。

管理ボックスの設置

news/index.twig の見出しセクション(<h1>News</h1> を含む <div>)の直前に、以下を追加してください。

@include("/admin/action.html")

管理用アセットの読み込み

news/index.twig<head> タグ内の管理UI用リソースが含まれていない場合は、<head> タグ内に以下を追加してください。トップページ(_top.twig)や詳細ページ(_entry.twig)と同様の記述です。

<link rel="stylesheet" href="/css/acms-admin.min.css">
{% set js = module('V2_Js') %}
<script src="{{ JS_LIB_JQUERY_DIR }}jquery-{{ JS_LIB_JQUERY_DIR_VERSION }}.min.js" charset="UTF-8"></script>
<script src="{{ ROOT_DIR }}acms.js{{ js.arguments }}" charset="UTF-8" id="acms-js"></script>

https://ablogcms-tutorial.ddev.site/news/ にアクセスし、ログイン状態で管理ボックスが横並びで正しく表示されることを確認してください。


まとめ

この章でやったこと:

  • module('V2_Entry_Summary', 'news_index') 関数でモジュールデータを取得し、entrySummary.items でループした

  • {% if entry.mainImage and entry.mainImage.path %} で画像の条件出力を実装した

  • {{ entry.mainImage.path | resizeImg(600) }} で画像リサイズ、{{ entry.summary | mb_trim(200, '...') }} でサマリー切り詰めを行った

  • {% if entrySummary.pagination.nextPage %} でページャーを実装した

  • モジュールIDの「メインイメージ対象」に entry_main_image を指定して画像フィールドと紐付けた

次の最終章では、サンプルデータをインポートして完成を確認します。


V2 GET モジュールの開発


V2 GETモジュールとは

V2 GETモジュールは、Twig テンプレート と連携する新しい形式の GET モジュールです。従来の GET モジュールと異なり、連想配列を返す ことで Twig 側で柔軟に表示を制御できます。

項目

従来の GET モジュール

V2 GET モジュール

基底クラス

ACMS_GET

Acms\Modules\Get\V2\Base

戻り値

文字列(HTML 等)

配列(構造化データ)

テンプレート

独自テンプレートエンジン

Twig

呼び出し

<!-- BEGIN_MODULE -->

module() 関数


ディレクトリ構造

独自 V2 モジュールは extension/acms/Modules/Get/V2/ に配置します。名前空間は Acms\Custom\Modules\Get\V2、オートロード済みのため require は不要です。

extension/acms/Modules/Get/V2/
└── Sample.php

雛形と規約

雛形

<?php

namespace Acms\Custom\Modules\Get\V2;

use Acms\Modules\Get\V2\Base;

/**
 * extension/acms/Modules/Get/V2/Sample.php
 *
 * テンプレート上では、Twig の module() 関数で呼び出されます。
 */
class Sample extends Base
{
    public function get(): array
    {
        return [
            'moduleTest' => 'Sample',
        ];
    }
}

クラス

  • Acms\Modules\Get\V2\Base を継承する

  • ファイルのパスと命名規則は PSR4 に従う

  • extension/acms の名前空間は Acms\Custom\Modules\Get\V2

モジュール名とクラス名の対応

テンプレートで使用するモジュール名は アンダースコア区切り です。モジュール名の _ は名前空間・クラス名の \ に対応します。

モジュール名

クラス名

ファイルパス

V2_Sample

Acms\Custom\Modules\Get\V2\Sample

Modules/Get/V2/Sample.php

V2_Own_Sample

Acms\Custom\Modules\Get\V2\Own\Sample

Modules/Get/V2/Own/Sample.php

extension/acms の独自モジュールは Acms\Custom\Modules 名前空間で解決され、標準モジュールより に検索されるため、同名で上書き可能です。

出力

get() メソッドで 配列 を return します。文字列は返しません。

public function get(): array
{
    return [
        'items' => [...],
        'count' => 10,
    ];
}

実行例

テンプレート(Twig)

{% set result = module('V2_Sample') %}
<p>{{ result.moduleTest }}</p>

実行結果

<p>Sample</p>

module() 関数

Twig テンプレートでは module() 関数で V2 モジュールを呼び出します。

{% set data = module(モジュール名, 識別子, コンテキスト) %}

引数

説明

第1引数

string

モジュール名(例: 'V2_Sample'

第2引数

string|null

モジュールIDの識別子。使わない場合は null

第3引数

array

外部コンテキストの指定

{% set result = module('V2_Sample', 'my-sample', {
    cid: 1,
    page: 1,
    limit: 10,
    keyword: null,
    tag: null,
    field: null,
    order: null,
    start: null,
    end: null
}) %}

モジュールID化

GETモジュールのID化 を参照してください


Base クラスのプロパティ

Acms\Modules\Get\V2\Base を継承したモジュールで利用できるプロパティです。

URL コンテキスト関連

プロパティ

説明

$this->bid

int|null

ブログID

$this->bids

int[]

ブログIDの配列

$this->cid

int|null

カテゴリーID

$this->cids

int[]

カテゴリーIDの配列

$this->eid

int|null

エントリーID

$this->eids

int[]

エントリーIDの配列

$this->uid

int|null

ユーザーID

$this->uids

int[]

ユーザーIDの配列

$this->page

int

ページ番号

$this->limit

int|null

取得件数

$this->keyword

string

キーワード

$this->tag

string

タグ

$this->tags

string[]

タグの配列

$this->field

string

フィールド検索

$this->Field

Field_Search

フィールド検索オブジェクト

$this->order

string

並び順

$this->start

string

検索開始日時

$this->end

string

検索終了日時

その他

プロパティ

説明

$this->Get

Field

GET パラメータ

$this->Post

Field_Validation

POST データ

$this->moduleContext

Field

モジュールコンテキスト

$this->mid

int|null

モジュールID

$this->mbid

int|null

モジュールIDのブログID

$this->identifier

string|null

モジュールID識別子


スコープと階層

スコープ(scopes)

$scopes で、URL コンテキストを localglobal で取得するかを制御します。

  • global: URL の情報を優先(表示ページのコンテキスト)

  • local: モジュールIDの設定やテンプレート指定を優先

protected $scopes = [
    'uid' => 'global',
    'cid' => 'global',
    'eid' => 'global',
    'keyword' => 'global',
    'tag' => 'global',
    'field' => 'global',
    'start' => 'global',
    'end' => 'global',
    'page' => 'global',
    'order' => 'global',
];

階層(axis)

$axis で、ブログ・カテゴリーの階層を指定します。

protected $axis = [
    'bid' => 'self',           // self | descendant-or-self | ancestor-or-self
    'cid' => 'self',
];

モジュールIDのコンフィグ

モジュールIDに紐づく設定を読み込むには loadModuleConfig() を使用します。

public function get(): array
{
    $config = $this->loadModuleConfig();
    $limit = (int) $config->get('my_limit', 10);
    $order = $config->get('my_order', 'datetime-desc');

    // ...
}

ヘルパーメソッド

基本パラメータをまとめて取得するには getBaseParams() を使用します。

$params = $this->getBaseParams();
// bid, bids, cid, cids, eid, eids, uid, uids, field, keyword, tag, tags,
// start, end, page, order, limit, blogAxis, categoryAxis を含む配列

その他

カスタムフィールド

モジュールIDでカスタムフィールドを有効にしている場合、buildModuleField() でフィールドデータを取得できます。$this->customFieldsEnabledtrue かつ $this->mid が設定されている場合に有効です。

$fields = $this->buildModuleField();

キャッシュ

$this->cacheLifetime が 0 より大きく、$this->identifier が設定されている場合、モジュールの実行結果がキャッシュされます。モジュールID使用時に自動的に有効化されます。

フック

V2 モジュール実行後には afterV2GetFire フックが呼ばれます。拡張アプリ等でフックを登録している場合は、レスポンス配列を加工できます。

// フックの引数: [ &$response, $this ]

管理画面でのデバッグ表示

管理者としてログインしている場合、実行結果に moduleInfo が付与されます。テンプレートで設定画面へのリンクなどを表示できます。

{{ include('/admin/module/setting.twig', { moduleInfo: result.moduleInfo }) }}

ブロックエディターのカスタマイズ


ブロックエディターのカスタマイズを管理画面から行えます管理画面 > 編集画面 > ブロックエディタ設定 から行えます。

管理ページのブロックエディター設定画面で、ブロックエディタのメニューや、追加できるブロックをカスタマイズできます。
ブロックエディター設定画面

画像リサイズ

ブロックエディターで追加したメディア画像のリサイズサイズを指定します。ブロックエディターでは、全てのメディア画像がこのサイズにリサイズされます(指定サイズより小さい画像はリサイズされません)

画像リサイズの設定をピクセスで指定します。
画像リサイズ設定

ブロックメニュー

ブロックエディターで追加できるブロック項目を設定できます。

ブロックメニューを追加・削除できます。
ブロックメニュー設定画面
  • ブロック:ブロックの種類

  • ラベル:メニュー表示で表示されるテキスト

  • クラス:追加したブロック要素に付与されるクラス

  • グループ:メニュー表示するときのグループを指定します。空の場合、上で設定されているグループが設定されます。

追加ブロックのメニュー表示に反映されます。
追加ブロックのメニュー表示

メニュー設定

メニュー設定では、テキストを選択したときのメニュー項目の制御ができます。不要な要素があればチェックを外してください。

使いたいメニューにはチェックを入れ、不要なメニューはチェックをはずします。
テキストのメニュー設定画面
テキストを選択することで、メニューが表示されます。
テキストの装飾メニュー

カスタムクラス

カスタムクラスでは、選択したテキストを span で囲って任意のクラスを設定するときの、クラスを設定できます。

*「メニュー設定」で「カスタムクラス」にチェックが入っている必要があります。

ラベルとクラス名を好きな数だけ設定します。
カスタムクラス設定画面
選択したテキストに、カスタムクラスで「注意ラベル」を設定してる例です。
カスタムクラスのメニュー表示例

画像サイズ

メディア画像の表示サイズの選択肢を設定できます。値は % で設定します。

画像サイズの選択肢をラベルと値(%)で設定
画像サイズ設定画面
画像のポップアップメニューのサイズ選択肢に表示されます。
画像サイズのメニュー表示例

カラーパレット

ブロックエディター内で使用するカラパレットの選択肢を設定します。

16進数のカラコードで指定します。(例:#330000)
カラーパレット設定画面
色選択UIの下に、設定したカラーのリストが表示されます。
カラーパレットの表示例

文字サイズ

選択したテキストのフォントサイズを変更する時の、文字サイズの選択肢を設定します。

*「メニュー設定」で「文字サイズ」にチェックが入っている必要があります。

ラベルと値(px,em,rem)のセットで、選択肢を設定します。
文字サイズ設定画面
選択したテキストの文字サイズを、文字サイズ選択肢から選択したサイズに変更します。
文字サイズのメニュー表示例

フォント

選択したテキストのフォントを変更する時の、フォントの選択肢を設定します。

*「メニュー設定」で「フォント」にチェックが入っている必要があります。

ラベルとフォント名のセットで、選択肢を設定します。
フォント設定画面
選択したテキストのフォントを、フォント選択肢から選択したフォントに変更します。
フォントのメニュー表示例

ブロックエディターの基本ブロック


配置機能やカラム機能を閲覧画面で利用する場合は、テーマ側でユニット機能利用時に閲覧側で必要になるCSS の適用が必要です。


ブロックエディターでは、スラッシュコマンド(/)の入力やブロックメニューから、さまざまな種類のブロックを挿入できます。ここでは、基本レイアウトのブロックについて説明します。

基本

段落

通常のテキストを記述するためのブロックです。デフォルトのブロックタイプであり、見出しやリスト以外のテキストは段落として扱われます。Enter を押すと次の段落になり、Shift + Enter で改行が挿入されます。

<p>...</p>

見出し

見出しレベル1〜6に対応するブロックです。文書の構造化やアウトラインの作成に使用します。

ブロック

ラベル

出力HTML

heading1

見出し1

<h1>...</h1>

heading2

見出し2

<h2>...</h2>

heading3

見出し3

<h3>...</h3>

heading4

見出し4

<h4>...</h4>

heading5

見出し5

<h5>...</h5>

heading6

見出し6

<h6>...</h6>

リスト

順序なしリスト(箇条書き)を挿入します。

<ul><li>...</li></ul>

番号付きリスト

順序付きリストを挿入します。

<ol><li>...</li></ol>

引用

引用文を記述するためのブロックです。

<blockquote>...</blockquote>

コード

コードブロックを挿入します。等幅フォントで表示され、改行やスペースがそのまま保持されます。

<pre><code>...</code></pre>

画像

メディアから画像を挿入するブロックです。メディアライブラリと連携し、大元のメディアで画像を差し替えると同一メディアIDを持つすべての画像ブロックが自動で更新されます。

編集メニューで設定できる項目:

  • 配置: 左・中央・右

  • 画像サイズ: 編集画面設定 > ブロックエディター設定で登録した選択肢(例: 100%, 75%, 66%)から選択。

  • キャプション・代替テキスト: アクセシビリティやSEOのためにも設定を推奨

  • リンク: 画像クリック時のリンク先、別タブで開くの有無

  • 拡大表示: デフォルトで有効。SmartPhoto によるライトボックス表示。

  • メイン画像に設定: 編集画面にメディアのカスタムフィールド(blockEditorConfig.setMainImageMark で指定)がある場合、そのフィールドに選択中の画像をセット可能

その他:

  • HTMLをコピー&ペーストしたとき、画像のURLが自サイト内の同一パスに存在するファイルを指している場合、相対パスに自動変換される

  • ペーストやURLで挿入した画像(メディア未登録)は、画像を選択した状態で表示されるアップロードボタンからメディアライブラリに登録できる

<div class="media-image-block align-{left|center|right}" data-type="imageBlock" data-align="..." data-width="..." data-mid="..." data-eid="..." data-no-lightbox="false">
  <figure style="max-width: ...;">
    <a href="..."><img src="..." alt="..." loading="lazy" data-mid="..." /></a>
    <figcaption class="caption">...</figcaption>
  </figure>
</div>

ファイル

メディアからファイル(PDF、Word、Excel など)を挿入するブロックです。画像以外のファイルをダウンロードリンクとして配置できます。

表示形式:

  • アイコン表示(デフォルト): ファイル種別のアイコンとキャプションを表示

  • ボタン表示: リンク風のボタンとして表示。キャプションの設定が必須

編集メニューで設定できる項目:

  • 配置: 左・中央・右(デフォルト: 左)

  • キャプション・代替テキスト: ボタン表示時はキャプションがリンクテキストになる

  • 別タブで開く: リンクを target="_blank" で開くかどうか

  • メディア選択・編集: メディアライブラリからファイルを選択・差し替え

<div class="media-file-block align-{left|center|right}" data-type="fileBlock" data-display-type="icon|button" data-icon="..." data-extension="..." data-file-size="...">
  <a href="...">
    <img src="..." alt="..." />
    <p class="caption">...</p>
  </a>
</div>

※ 別タブで開くが有効な場合は target="_blank"rel="noopener noreferrer" が付与されます。

リンクボタン

ボタン風のリンクを挿入するブロックです。ブロック内でテキストを直接編集でき、そのテキストがボタンのラベルになります。CTA(Call to Action)やダウンロードリンクなどに適しています。

編集メニューで設定できる項目:

  • 配置: 左・中央・右(デフォルト: 中央)

  • リンクURL: クリック時の遷移先

  • 別タブで開く: target="_blank" の有無

操作:

  • ブロックを選択してテキストを入力すると、ボタンに表示される文言を編集できる

  • Enter で次のブロックへ、Backspace で空の場合はブロック削除

<div class="link-button-block align-{left|center|right}" data-type="linkButton" data-align="...">
  <a href="..." class="link-button-block-link" data-type="button">ボタンのテキスト</a>
</div>

テーブル

表を挿入するブロックです。デフォルトで3行×3列のテーブルが作成されます。行・列の追加・削除、セルの結合、ヘッダー行の設定、横スクロール表示の設定が可能です。

<div class="tableWrapper"><table>...</table></div>

区切り線

文章の途中に区切り線を挿入するブロックです。セクションの区切りなどに使用します。

<div data-type="horizontalRule"><hr></div>

レイアウト

2カラムに分割

コンテンツを2カラムのレイアウトに分割します。各カラム内で通常通りブロックの追加・編集が可能です。

<div data-type="columns" data-layout="two-column">
  <div data-type="column">...</div>
  <div data-type="column">...</div>
</div>

3カラムに分割

コンテンツを3カラムのレイアウトに分割します。

<div data-type="columns" data-layout="three-column">
  <div data-type="column">...</div>
  <div data-type="column">...</div>
  <div data-type="column">...</div>
</div>

第7回:サンプルデータをインポートして完成を確認しよう


この章でやること

  • 既存のお知らせエントリーを削除し、サンプルデータをインポートする

  • 完成確認チェックリストで動作を網羅的に確認する

  • 次のステップ(フォームのTwig実装)への道筋を把握する

1. エントリーを削除する

a-blog cms は、エントリー単位でのエクスポート&インポートが可能です。

  1. 管理画面の「エントリー管理」を開く

  2. カテゴリー「お知らせ」を選択して検索する

  3. 表示されたエントリーをすべてチェックする

  4. 一括操作のSELECTメニューから「ゴミ箱」を選択し、実行する

8-2. インポートする

  1. インポートデータ : news_improt_data.zip をダウンロードします。

  2. (エントリー作成)ボタンの右横にある 「その他」メニュー → 「インポート」 を選択します。

  3. エントリーインポート画面 が表示されます。

  4. ステータスを「公開でインポート」に設定し、ファイルを選択してインポートを実行します。

SCR-20250826-bdfw

インポートが完了したら、https://ablogcms-tutorial.ddev.site/news/ を開いて新しいお知らせが反映されていることを確認してください。

3. 完成確認チェックリスト

チュートリアルで実装した3つのメインテンプレート(トップ・一覧・詳細)が正しく動作しているか、以下の順序で確認しましょう。各項目は該当する章の実装内容に対応しています。

確認の流れ

トップページ → 一覧ページ → 詳細ページの順に、実際にクリックしながら確認すると効率的です。


トップページ(_top.twig)— 第4章で実装

#

確認項目

該当実装

1

お知らせ一覧に「お知らせ」カテゴリーの記事が5件表示される

モジュールID news_top の表示件数

2

日付が 2025.08.07 の形式で表示される

date('Y.m.d') フィルター

3

カテゴリー名が正しく表示される

{{ entry.category.items[0].name }}

4

記事タイトルをクリックすると詳細ページに遷移する

{{ entry.url }}

5

管理ボックスが横並びで表示される

@include("/admin/action.html")

6

管理者がモジュールにホバーすると「編集」リンクが表示される

{{ include('/admin/module/setting.twig', ...) }}


一覧ページ(news/index.twig)— 第6章で実装

#

確認項目

該当実装

1

お知らせが3件ずつ表示される

モジュールID news_index の表示件数

2

記事に画像が設定されている場合、サムネイルが表示される

{% if entry.mainImage and entry.mainImage.path %} + resizeImg(600)

3

サマリーが200文字で切り詰められて表示される

mb_trim(200, '...') フィルター

4

「もっと見る」をクリックすると2ページ目に遷移する

{% if entrySummary.pagination.nextPage %}

5

最終ページでは「もっと見る」が表示されない

entrySummary.pagination.nextPage が空のとき非表示


詳細ページ(news/_entry.twig)— 第5章で実装

#

確認項目

該当実装

1

記事ごとに異なるタイトル・本文が表示される

module('V2_Entry_Body', null, { eid: EID })

2

日付が 2025年8月7日 の形式で表示される

entry.datetime + date フィルター

3

カテゴリー名が表示され、クリックするとカテゴリーURLに遷移する

{{ entry.category.items[0].url }}

4

タグが設定されている記事では #タグ名 が表示される

{% for tag in entry.tags %}

5

ブラウザのタブに記事タイトルが表示される

{{ ENTRY_TITLE }}

6

パンくずリストに記事タイトルが表示される

{{ ENTRY_TITLE }}

7

エントリー編集ボックスが表示される(ログイン状態)

{{ include('admin/entry/action.twig', { entry }) }}


共通項目

#

確認項目

該当実装

1

すべてのページで管理ボックスが正しいデザインで表示される

acms-admin.min.css + acms.js

2

ログアウト状態では管理ボックスおよびエントリー編集ボックスが非表示になる

moduleInfo は管理者のみ

3

CSS・JavaScriptのパスに /themes/sample/ が自動付与されている

a-blog cms のパス補完

4

<meta name="generator" content="a-blog cms" /> が出力されている

CMS経由表示の確認


4. Twig 構文のエラーについて

Twig 構文にエラーがあるとデバッグモード時に以下のようなエラーメッセージが表示されます。

このようなエラーが出た場合、Twig のエラーメッセージを確認すると原因を特定しやすくなります。エラー画面には次の情報が表示されます。

  • エラー内容:何が問題か(例:Unknown "dete" filter

  • ファイル名と行番号:どのテンプレートの何行目か(例:news/_entry.twig line 137)

  • 修正のヒント:Twig が推測してくれる場合がある(例:Did you mean "date"?

フィルター名のタイプミス

フィルター名を間違えると「Unknown "○○" filter」と表示されます。たとえば datedete と打ち間違えると、次のようなエラーになります。

Unknown "dete" filter. Did you mean "date" in "news/_entry.twig" at line 137?

エラーメッセージの「Did you mean "date"?」を手がかりに、該当行のフィルター名を確認して修正してください。

5. 次のステップ

このチュートリアルではお知らせ機能のCMS化を扱いました。実務ではさらに以下の実装が必要になります。

お問い合わせフォームのCMS化

サンプルサイトの contact/ フォームはまだ静的なHTMLのままです。a-blog cmsにはフォーム機能が標準搭載されており、入力画面・確認画面・送信完了画面をテンプレートとして実装できます。

フォーム機能のドキュメントを参考に実装してみましょう。

テンプレート継承の活用

このチュートリアルでは各テンプレートに <head> や管理UIリソースを個別に書きました。Twigのテンプレート継承{% extends %}{% block %})を使うと、共通部分を親テンプレートに集約して保守性を高められます。

さらに詳しく学ぶ


まとめ

この章でやったこと:

  • サンプルデータをインポートし、完成確認チェックリストで動作を確認した

  • Twig 構文のエラーについての確認ポイントを把握した

  • フォームのCMS化・テンプレート継承など、次のステップへの道筋を確認した

このチュートリアルを終えて、静的HTMLを a-blog cms のTwig テーマとして動かす基本フローが身につきました。標準テンプレートとの最大の差分は「module() 関数でデータを取得し、モジュールごとの返り値の構造に応じて出力する記法」です。これらを押さえれば、モジュールIDによる設定管理など、a-blog cmsとしての仕組みは標準テンプレートと変わりません。ぜひ次のプロジェクトからTwig テンプレートでのテーマ開発を試してみてください。