PowerCMS X ブログ
2021-10-13
PowerCMS Xのテンプレート・エンジンである PAML(PHP Alternative Template Language)は PowerCMS X ver.3 で刷新され、OSS版も公開しました。
この記事では、新しくなったテンプレート・エンジンについてご紹介します。
PowerCMS X ver.3.0のテンプレートエンジン PAML3では、タグデリミタのカスタマイズによって、Mustache, Twig, Smartyライクな記述が可能になり、変数のスコープの指定やタグ属性への配列やハッシュの指定が簡単になるなど多数の変更があり、一部 if文の評価結果や値の取得結果が従来と異なる可能性があるため、デフォルトでは従来バージョンが利用されるようになっています。環境変数の指定によって新しいバージョンを選択できるようになります。
新しいテンプレートエンジンを利用するには環境変数「paml_version」に「3」を指定、タグデリミタで他のテンプレートエンジンライクな記述を利用するためには「tag_delimiter」にMustache, Twig, Smartyのいずれかを指定します(※paml_versionは管理画面の環境変数では設定できません)。
"paml_version" : 3,
"tag_delimiter" : "Mustache",
今回のバージョンアップにあたり、テンプレートエンジンを刷新した理由、そして、目指したものについて少し説明させていただきます。
PowerCMS / PowerCMS X のテンプレート記法、MTタグ(MTML) は確かに歴史があり、経験者もそれなりにいるのですが、2021年現在、CMSやテンプレートエンジンのシェア的にも決して安泰ではないと考えました。では、初学者にとってとっつきやすいかどうかを考えると、それもまたどうなんだろうという思いが拭えません。
ざっと調べると
情報が公開されていない商用CMSなどは、正しくない場合があるかと思いますが、このような分布? になります。Twigについては CMSではありませんが、PHPの Laravelなどでも利用されています。
一方で、CMSを離れてみると
など、一部重複していますが、このあたりを利用しているケースが多いのではないかと思います。
また、それとは別に JavaScriptフレームワークを好むフロントエンド開発者も増えています。SSG(静的サイトジェネレーター)としても利用できたりして、それが一定の流行になっています。
PowerCMS X / PowerCMS では静的ファイルを出力できることがこれまでも支持された一つの大きな要因ですし、PowerCMS X では従来比 20倍のパブリッシュ速度を実現してます。インフラ管理が嫌で、じゃぁ、サーバーレスということであれば、クラウドサービス アイコン別ウィンドウで開きます も提供していますし、AWS の S3や CloudFrontとの連携 アイコン別ウィンドウで開きます も容易です(AWS連携を強化したことも、この記事で書いているような背景を意識したものではありますが)。
それらを受けて、では、リニューアルにあたって意識したことは以下のようなこととなります。
ターゲットとしているのは、JavaScriptや PHPなどを普段書いている開発者、開発初心者となります。
変数の設定については、これまでは setvarタグもしくは varタグに nameとvalueを指定する方法でした。
<mt:setvar name="_name" value="_value">
新しいバージョンでは var、let、setが利用でき、よりシンプルに書くことができます。このうち letのみブロック内でのみ有効なローカル変数となります。
<mt:var _name=_value>
<mt:let _name=_value>
<mt:set _name=_value>
Mustach互換であれば
{{var _name=_value}}
{{set _name=_value}}
{{let _name=_value}}
※ 変数名の頭に「_」(アンダースコア)を付けているのは、例えば var name=としてしまうと従来からある <mt:var name="値">(変数のセットではなく、出力)と被ってしまうためです。
また、配列を「.」(ドット)で繋ぐことで直感的に扱えるようになります。以下はMustache互換モードでの記述です。
{{let entries.0.title="記事タイトル0"}}
{{let entries.0.text="記事本文0"}}
{{let entries.1.title="記事タイトル1"}}
{{let entries.1.text="記事本文1"}}
これまで、foreachは単にloopのエイリアス、forはfromからtoまでのループのためのタグでした。
新しいバージョンでは、配列をループ出力する際に、下記のような書き方が可能になります。
<mt:for entry in entries>
<mt:var name="entry.title">
</mt:for>
Twig互換であれば
{% for entry in entries %}
{{ entry.title }}
{% endfor %}
foreach は以下のように書けます。
<mt:foreach entries as entry>
<mt:var name="entry.title">
</mt:foreach>
Mustach互換であれば
{{#foreach entries as entry}}
{{entry.title}}
{{/foreach}}
これらの組み合わせにより、以下のように書けるようになります。
{{let entries.0.title="記事タイトル0"}}
{{let entries.0.text="記事本文0"}}
{{let entries.1.title="記事タイトル1"}}
{{let entries.1.text="記事本文1"}}
{{#foreach entries as entry}}
{{entry.title}}
{{entry.text}}
{{/foreach}}
オールインワンで提供できているわけですから、切り離す必要はないように思います(今もそう思います)。ただ、PowerCMS Xは OSSではないですし、こんな話も出てきているわけで、それであれば、我々として一つの回答をさせていただきたいと思ったということでもあります。
新しいテンプレートエンジン PAML3は SSGとして利用できます。以下は Twig互換モードで PowerCMS Xの新バージョンでサポートされた RESTful APIから取得した JSONをスタティックな HTMLとして出力するテンプレートの例です。
{% extends file=extends/twig.tpl %}
{% let _title='Generating static files...' %}
{% block name="title" %}{{ _title|remove_html }}{% endblock %}
{% block name="body" %}
{# Fetch JSON from API. #}
{% fetch url=$end_point from_json=results %}
{{ results.items set=entries }}
{% for entry in entries %}
{# Set the local variable in loop. #}
{% let _title=$entry.title %}
{# Build each HTML. #}
{% include file=includes/twig.tpl set=content %}
{# Generate the path. #}
{% set path %}{{ base_path }}{% if entry.categories is defined %}{{ entry.categories.0.Path }}/{% endif %}{{ entry.basename }}.html{% endset %}
{# Output the file. #}
{% fileput path=$path contents=$content set=result %}
{# Display or stdout the results. #}
{% if name=__first__ %}
{% if name=sapi ne=cli %}<ul>{% endif %}
{% endif %}
{% if name=sapi ne=cli %}<li>{% endif %}
{% if name=result %}
Generated the entry '{{ _title|escape }}' to file '{{ path }}'.
{% else %}
Failed generate the entry '{{ _title|escape }}' to file '{{ path }}'.
{% endif %}
{% if name=sapi ne=cli %}</li>{% endif %}
{% if name=__last__ %}
{% if name=sapi ne=cli %}</ul>{% endif %}
{% endif %}
{% endfor %}
{# Get the variable out of the loop. #}
<p>{{ _title }} done.</p>
{% endblock %}
実はこれまでのバージョンでもできたのですが、from_jsonモディファイアでJSONを配列に変換して変数にセットでき、to_jsonモディファイアで配列をJSON文字列に変換することができます。
<mt:for from_json="entry">
{
"title" : "記事のタイトル",
"text" : "<p>これは記事の本文です。<\/p>",
"published_on": "20211013100000",
"tags" : ["プレスリリース", "製品情報"]
}
</mt:for>
<h1><mt:var name="entry.title"></h1>
<p class="date">
公開日 : <mt:var name="entry.published_on" format_ts="Y-m-d H:i:s">
</p>
<div>
<mt:var name="entry.text">
</div>
<mt:foreach entry.tags as tag>
<mt:if name="__first__"><ul></mt:if>
<li><mt:var name="tag"></li>
<mt:if name="__last__"></ul></mt:if>
</mt:foreach>
新しいバージョンで追加された RESTful APIを利用、もしくは RESTful APIで得られるデータを取得できるテンプレート・タグ「objecttoresource(objecttojson)」ファンクション・タグが追加されています。
<!DOCTYPE html>
<html lang="<mt:websitelanguage>">
<head>
<title><mt:entrytitle escape></title>
</head>
<body>
<h1><mt:entrytitle></h1>
<div>
<mt:entrybody>
</div>
</body>
</html>
{{objectToResouce let="entry"}}
<!DOCTYPE html>
<html lang="{{websitelanguage}}">
<head>
<title>{{entry.title|escape}}</title>
</head>
<body>
<h1>{{entry.title}}</h1>
<div>
{{entry.text}}
</div>
</body>
</html>
objecttoresourceタグは、現在のコンテキストのオブジェクトを RESTful APIが返却するデータと同じ形で配列にして返すファンクションタグです。従来の書き方もそのまま可能ですが、新しい書き方であれば、モデルごとに異なるタグ名を使うことなくシンプルなルールさえ覚えればビューを書くことができるようになります。
カテゴリー:テンプレート作成Tips | 技術情報 | リリース&アップデート情報
投稿者:Junnama Noda