🛠️

a-blog cms を利用して静的HTMLサイトからCMSのテーマを作ってみよう 2022年版 その2「カスタムフィールド編」

2022/05/26に公開

a-blog cms の機能にカスタムフィールドというものがあります。まずは、カスタムフィールド全般の説明をしつつ、その後テーマに実際の実装をしていきます。

https://zenn.dev/kazumich/articles/a93a119c6b47e1

の続編になりますので、その1「エントリー編」がまだの方は合わせてご覧ください。

カスタムフィールドとは

管理画面上に標準で用意されている入力欄ではなく、カスタマイズする人が欲しい追加された入力欄のことです。一般的にテーマ作成では、サイトの閲覧者がアクセスする表側のテンプレートを作ることになりますが、カスタムフィールドについては管理画面のテンプレートを作ることで希望の管理画面の UI を構築していきます。

カスタムフィールドの種類と、そのテンプレートのファイルの置き場は以下のようになります。

カスタムフィールドの種類 テンプレートファイル
エントリー カスタムフィールド /themes/sample/admin/entry/field.html
カテゴリー カスタムフィールド /themes/sample/admin/category/field.html
ブログ カスタムフィールド /themes/sample/admin/blog/field.html
ユーザー カスタムフィールド /themes/sample/admin/user/field.html
モジュール カスタムフィールド /themes/sample/admin/module/field.html

カスタムフィールドの作り方

a-blog cms のカスタムフィールドは、フォームの HTML を用意するのですが、入力ミスで動作しなくなることから「カスタムフィールドメーカー」というツールが管理ページやデベロッパーサイト上で提供されています。

管理ページ > コンフィグ > このブログの初期コンフィグ > ガイドライン/ツール > カスタムフィールドメーカー

https://developer.a-blogcms.jp/tools/custom-field.html

ヘッダー・フッターの編集用の管理画面の作成

カスタムフィールドの基礎の紹介が終わったので、ここからテンプーレートを実装を進めます。このヘッダー・フッター部分は、サイト全体どこでも利用するデータということになりますので、ブログのカスタムフィールドを利用します。

ヘッダー部分は、アイコンとタイトルを編集可能にします。

フッター部分は、左側の会社名・郵便番号・住所・電話番号と、右側にある SNSアイコンのリンク先を設定したり、使わないものは消したりできるようにしてみます。

カスタムフィールドメーカーを利用して以下の情報から管理画面のフォームのHTMLを作成します。入力用ソース のエリアに書かれたフォームのHTMLを単体のファイルとして、 /themes/sample/admin/blog/field.html に保存します。

ヘッダー情報

入力欄の種類 タイトル フィールド
メディア アイコン site-icon
テキスト サイト名 site-name
<table class="acms-admin-table-admin-edit">
  <tr>
    <th>アイコン</th>
    <td class="js-media-field">
      <div class="js-droparea" data-thumbnail="{site-icon@thumbnail}" data-type="image" data-thumbnail-type="{site-icon@type}" data-width="200px" data-height="200px"></div>
      <p class="js-text acms-admin-text-danger" style="display:none">許可されていないファイルのため挿入できません。</p>
      <div class="acms-admin-margin-top-mini">
        <button type="button" class="js-insert acms-admin-btn" data-type="image">メディアを選択</button>
      </div>
      <input type="hidden" name="site-icon" value="{site-icon}" class="js-value" />
      <input type="hidden" name="field[]" value="site-icon" />
      <input type="hidden" name="site-icon:extension" value="media" />
    </td>
  </tr>
  <tr>
    <th>サイト名 </th>
    <td>
      <input type="text" name="site-name" value="{site-name}" class="acms-admin-form-width-full" />
      <input type="hidden" name="field[]" value="site-name" />
    </td>
  </tr>
</table>

会社情報

入力欄の種類 タイトル フィールド
テキスト 会社名 company-name
テキスト 郵便番号 zip
テキスト 住所 address
テキスト 電話番号 tel
<table class="acms-admin-table-admin-edit">
  <tr>
    <th>会社名</th>
    <td>
      <input type="text" name="company-name" value="{company-name}" class="acms-admin-form-width-full" />
      <input type="hidden" name="field[]" value="company-name" />
    </td>
  </tr>
  <tr>
    <th>郵便番号</th>
    <td>
      <input type="text" name="zip" value="{zip}" class="acms-admin-form-width-full" />
      <input type="hidden" name="field[]" value="zip" />
    </td>
  </tr>
  <tr>
    <th>住所</th>
    <td>
      <input type="text" name="address" value="{address}" class="acms-admin-form-width-full" />
      <input type="hidden" name="field[]" value="address" />
    </td>
  </tr>
  <tr>
    <th>電話番号</th>
    <td>
      <input type="text" name="tel" value="{tel}" class="acms-admin-form-width-full" />
      <input type="hidden" name="field[]" value="tel" />
    </td>
  </tr>
</table>

SNS情報

入力欄の種類 タイトル フィールド
テキスト Facebook facebook
テキスト Twitter twitter
テキスト YouTube youtube
<table class="acms-admin-table-admin-edit">
  <tr>
    <th>Facebook</th>
    <td>
      <input type="text" name="facebook" value="{facebook}" class="acms-admin-form-width-full" />
      <input type="hidden" name="field[]" value="facebook" />
    </td>
  </tr>
  <tr>
    <th>Twitter</th>
    <td>
      <input type="text" name="twitter" value="{twitter}" class="acms-admin-form-width-full" />
      <input type="hidden" name="field[]" value="twitter" />
    </td>
  </tr>
  <tr>
    <th>YouTube</th>
    <td>
      <input type="text" name="youtube" value="{youtube}" class="acms-admin-form-width-full" />
      <input type="hidden" name="field[]" value="youtube" />
    </td>
  </tr>
</table>

これらをテンプレート上に設定すると管理画面に入力欄が表示されます。

ここまで作ると、やっとテンプレート側の実装になります。

ヘッダーの表示側の実装

管理画面が出来上がると、次はそのデータを表示できるようにします。

今回はブログのカスタムフィールドを表示させます。表示にはブログフィールドを利用します。カスタムフィールドモジュールの中で利用する {変数} は、制作者側で用意していますので、中身は空っぽになっています。

<!-- BEGIN_MODULE Blog_Field -->

<!-- END_MODULE Blog_Field -->

修正する場所は <div class="header-logo"> になります。

<div class="header-logo">
  <div>
    <h1 class="site-name"><a href="index.html">
      <img src="/images/ablogcms_mark.png" alt="ablogcms" class="site-logo"><span class="siteNameText">sample static site</span></a>
    </h1>
  </div>
</div>

表示用のコードについても、カスタムフィールドメーカーの表示用ソースを参考に、以下のように書き換えます。

<!-- BEGIN_MODULE Blog_Field -->
<div class="header-logo">
  <div>
    <h1 class="site-name"><a href="index.html">
      <img src="%{MEDIA_ARCHIVES_DIR}{site-icon@path}" alt="{site-name}" class="site-logo"><span class="siteNameText">{site-name}</span></a>
    </h1>
  </div>
</div>
<!-- END_MODULE Blog_Field -->

IFブロックを利用して条件分岐の設定をする

先ほど最低限の実装を済ませましたが、もう少ししっかり作り込みを行います。 CMS ではデータがある時に出すのは当たり前ではありますが、無い時にどうするのかも大事です。例えばアイコンが無い時に何もしてないと、画像のパスが無いまま<img>だけ残ってしまうことになります。

IFブロックを利用するとテンプレートに条件分岐を設定できます。

https://developer.a-blogcms.jp/document/template/if.html

<div class="header-logo">
  <div>
    <h1 class="site-name"><a href="index.html">
      <!-- BEGIN_IF [{site-icon@path}/nem] -->
      <img src="" alt="{site-name}" class="site-logo">
      <!-- END_IF -->
      <span class="siteNameText">
      <!-- BEGIN_IF [{site-name}/nem] -->
        {site-name}
      <!-- ELSE -->
        %{BLOG_NAME}
      <!-- END_IF -->
    </span>
    </a>
    </h1>
  </div>
</div>

フッターの表示側の実装

ヘッダーと同じようにフッター部分も実装をしていきます。こちらもデータが無い時にタグが残らないような実装をする必要がありますが、IFブロックより手軽な :veilブロック (<!-- BEGIN xxx:veil --> 〜 <!-- END xxx:veil -->) を使ってみます。

:veilブロックは、 BEGIN 〜 END の中に {変数} が複数あったとして、何も編集されなかったら、囲まれているエリアは無かったことにできるというブロックです。

https://developer.a-blogcms.jp/document/template/veil.html

編集前

<address class="acms-col-md-4">
  <dl class="company-about">
    <dt class="company-name">有限会社アップルップル</dt>
    <dd class="company-detail">〒450-0002</dd>
    <dd class="company-detail">名古屋市中村区名駅3-18-5 モンマートビル5F</dd>
    <dd class="company-detail">TEL : <a href="tel:052-485-8577">052-485-8577</a></dd>
  </dl>
</address>
<div class="acms-col-md-8">
  <div class="acms-hide acms-block-lg acms-block-xl">
    <ul class="sns-list">
      <li class="sns-list-item"><a href="https://www.facebook.com/ablogcms" class="sns-list-facebook"><span class="acms-icon-facebook"></span></a></li>
      <li class="sns-list-item"><a href="https://twitter.com/ablogcms" class="sns-list-twitter"><span class="acms-icon-twitter"></span></a></li>
      <li class="sns-list-item"><a href="https://www.youtube.com/user/ablogcmsTube" class="sns-list-youtube"><span class="acms-icon-youtube"></span></a></li>
    </ul>
  </div>
</div>

以下のような実装になりました。{変数}毎に :veil で囲み、データが無い時には、<dd> が無くなるように設定しています。全部書いてない時には <dl> や <ul> も消えるように company:veil というものも用意しました。その外の <address class="acms-col-md-4"> や <div class="acms-col-md-8"> を囲むとレイアウトがズレる可能性があるので残すようにしています。

編集後
<!-- BEGIN_MODULE Blog_Field -->
<address class="acms-col-md-4">
  <!-- BEGIN company:veil -->
  <dl class="company-about">
    <!-- BEGIN company-name:veil --><dt class="company-name">{company-name}</dt><!-- END company-name:veil -->
    <!-- BEGIN zip:veil --><dd class="company-detail">〒{zip}</dd><!-- END zip:veil -->
    <!-- BEGIN address:veil --><dd class="company-detail">{address}</dd><!-- END address:veil -->
    <!-- BEGIN tel:veil --><dd class="company-detail">TEL : <a href="tel:{tel}">{tel}</a></dd><!-- END tel:veil -->
  </dl>
  <!-- END company:veil -->
</address>
<div class="acms-col-md-8">
  <!-- BEGIN sns:veil -->
  <div class="acms-hide acms-block-lg acms-block-xl">
    <ul class="sns-list">
      <!-- BEGIN facebook:veil --><li class="sns-list-item"><a href="{facebook}" class="sns-list-facebook"><span class="acms-icon-facebook"></span></a></li><!-- END facebook:veil -->
      <!-- BEGIN twitter:veil --><li class="sns-list-item"><a href="{twitter}" class="sns-list-twitter"><span class="acms-icon-twitter"></span></a></li><!-- END twitter:veil -->
      <!-- BEGIN youtube:veil --><li class="sns-list-item"><a href="{youtube}" class="sns-list-youtube"><span class="acms-icon-youtube"></span></a></li><!-- END youtube:veil -->
    </ul>
  </div>
  <!-- END sns:veil -->
</div>
<!-- END_MODULE Blog_Field -->

カテゴリー毎のヘッダーの実装

次は list.html と entry.html のヘッダー部分の仕上げを行います。現状は、カテゴリー名と書かれていますが、それぞれのカテゴリー名が編集されるようにします。また、黒い部分には背景画像を設定し、「カテゴリーの説明文が書かれます。」の部分も編集可能にします。

まずは修正する場所は <div class="page-title-wrapper"> になります。

<div class="page-title-wrapper" style="background-image: url(/images/header.jpg);">
  <div class="page-title-filter"></div>
  <div class="page-title-inner">
  	<div class="acms-container">
    <p class="page-title">カテゴリー名</p>
    <p class="page-description">カテゴリーの説明文が書かれます。</p>
  	</div>
  </div>
</div>

グローバル変数を利用

a-blog cms のグローバル変数を利用すると、簡単にカテゴリー名が設定できます。通常の変数は中括弧(波括弧)を利用して {変数} を設定しますが、グローバル変数は %{変数} のように中括弧の前にパーセントがついています。どのようなグローバル変数があるのかは、デベロッパーサイトのドキュメントのグローバル変数をご覧ください。

https://developer.a-blogcms.jp/document/reference/global_variable.html

ヘッダー部分でも実は %{BLOG_NAME} と実装結果の HTML には書いてありましたが、カテゴリー毎に変わっているところで確認してもらった方が分かりやすいかと説明しないでいました。

カテゴリー名のグローバル変数は %{CATOGORY_NAME} と書きます。

<div class="page-title-wrapper" style="background-image: url(/images/header.jpg);">
  <div class="page-title-filter"></div>
  <div class="page-title-inner">
  	<div class="acms-container">
    <p class="page-title">%{CATEGORY_NAME}</p>
    <p class="page-description">カテゴリーの説明文が書かれます。</p>
  	</div>
  </div>
</div>

これで http://localhost/news/http://localhost/recruit/ を表示させると「お知らせ」や「採用情報」という表示が出るようになります。

カテゴリーカスタムフィールド管理画面の作成

次に、背景画像と説明文はカテゴリーのカスタムフィールドを利用します。項目としては以下のような項目になりますので、カスタムフィールドメーカーを利用し管理画面のフォームのHTMLを作成します。入力用ソース のエリアに書かれたフォームのHTMLを単体のファイルとして、 /themes/sample/admin/category/field.html に保存します。

入力欄の種類 タイトル フィールド
メディア 背景画像 category-image
テキストエリア 説明文 category-description
<table class="acms-admin-table-admin-edit">
  <tr>
    <th>背景画像</th>
    <td class="js-media-field">
    <div class="js-droparea" data-thumbnail="{category-image@thumbnail}" data-type="image" data-thumbnail-type="{category-image@type}" data-width="200px" data-height="200px"></div>
    <p class="js-text acms-admin-text-danger" style="display:none">許可されていないファイルのため挿入できません。</p>
    <div class="acms-admin-margin-top-mini">
      <button type="button" class="js-insert acms-admin-btn" data-type="image">メディアを選択</button>
    </div>
    <input type="hidden" name="category-image" value="{category-image}" class="js-value" />
    <input type="hidden" name="field[]" value="category-image" />
    <input type="hidden" name="category-image:extension" value="media" />
    </td>
  </tr>
  <tr>
    <th>説明文</th>
    <td>
    <textarea name="category-description" class="acms-admin-form-width-full">{category-description}</textarea>
    <input type="hidden" name="field[]" value="category-description" />
    </td>
  </tr>
</table>

これらをテンプレート上に設定すると管理画面に入力欄が表示されます。

カテゴリーカスタムフィールド表示側の実装

ブログのカスタムフィールドで行った事の繰り返しになりますが、今回はカテゴリーになりますので、利用するモジュールはカテゴリーフィールドを利用します。

<!-- BEGIN_MODULE Category_Field -->

<!-- END_MODULE Category_Field -->

ブログのカスタムフィールドと同様なので、以下 HTML は見ないで、実装が完了したら答え合わせにご利用ください。

<!-- BEGIN_MODULE Category_Field -->
<div class="page-title-wrapper" style="background-image: url(%{MEDIA_ARCHIVES_DIR}{category-image@path});">
  <div class="page-title-filter"></div>
  <div class="page-title-inner">
    <div class="acms-container">
      <p class="page-title">%{CATEGORY_NAME}</p>
      <!-- BEGIN description:veil -->
      <p class="page-description">{category-description}[nl2br4html]</p>
      <!-- END description:veil -->
    </div>
  </div>
</div>
<!-- END_MODULE Category_Field -->

今回、見慣れない [nl2br] という記述が見つかります。 これは a-blog cms の機能で、校正オプション と呼びます。{変数}の値を利用し情報を編集するようなプログラムを実行することができます。

https://developer.a-blogcms.jp/document/reference/proofreading.html

{category-description}[nl2br4html] と記述することで、{category-description} の改行コードを <br> に置き換える処理を行います。

カテゴリーの管理画面から、データを入れることで以下のような表示となりました。


今回はカスタムフィールドを中心に、テンプレートで使う機能を紹介しました。

  • ブログのカスタムフィールドでヘッダー・フッターの編集
  • カテゴリーのカスタムフィールドでカテゴリーヘッダーの編集
  • 条件分岐をするための IFブロックや :veilブロックの紹介
  • グローバル変数の利用
  • 校正オプションの利用

それらしくなってきましたが、まだまだな部分もあります。 その3 で、さらに完成度を高めていきます!

https://zenn.dev/kazumich/articles/c46db53215f901

Discussion