KurocoのSmarty基本構文
Kurocoでは、カスタム処理やバッチ処理のテンプレートエンジンとしてSmartyを使用しています。このドキュメントでは、KurocoのSmarty実装を扱う上で必要な基本的な構文要素について説明します。
制御構造
if/else/elseif文
{if}文は条件に基づいた処理の分岐を可能にします。{else}と{elseif}を使用して複数の条件を処理できます。
構文
{if 条件}
条件が真の場合の処理
{elseif 条件2}
条件2が真の場合の処理
{else}
すべての条件が偽の場合の処理
{/if}
例
{if $member.status == 'active'}
おかえりなさい!
{else}
アカウントが無効です。
{/if}
if文で使用可能なPHP関数
{if}文内で使用できるPHP関数は以下に限定されています。リストにない関数を条件式で呼ぶと、コンパイル時にエラーとなります。
is_null()- 変数がnullかどうかをチェックcount()- 配列の要素数をカウントis_array()- 変数が配列かどうかをチェックin_array()- 値が配列内に存在するかチェックisset()- 変数が宣言されており、nullでないかチェックis_object()- 変数がオブジェクトかどうかをチェック
なお、null / NULL、true / TRUE、false / FALSE は裸の語として条件式に書けます。これ以外の判定が必要な場合は、事前に {assign} やモディファイアで真偽値を計算し、その結果を {if} で評価してください。
詳細はKurocoのSmartyで利用可能なPHP関数を参照してください。
ループ構造
foreach文
{foreach}文は、配列やオブジェクトを反復処理します。
基本構文
{foreach from=$array item="item"}
{$item}
{/foreach}
インデックス付き
{foreach from=$array item="item" key="key"}
{$key}: {$item}
{/foreach}
ループカウンター付き
{foreach from=$array item="item" name="loop1"}
{$item}
{if !$smarty.foreach.loop1.last}
,
{/if}
{/foreach}
例
{foreach from=$topics_list.list item="topics"}
{logger msg1=$topics.subject}
{/foreach}
foreachのプロパティ
name属性を使用すると、以下のプロパティにアクセスできます:
$smarty.foreach.name.first- 最初の反復でtrue$smarty.foreach.name.last- 最後の反復でtrue$smarty.foreach.name.index- 現在の配列インデックス(0から開始)$smarty.foreach.name.iteration- 現在の反復回数(1から開始)$smarty.foreach.name.total- 反復の総数
複雑な例
{capture name="emailBody"}
{$member.name1} 様
お知らせがあります。
{/capture}
{foreach from=$members item="member" name="memberLoop"}
{sendmail
var='result'
to=$member.email
subject='お知らせ'
contents=$smarty.capture.emailBody
from="noreply@example.com"
from_nm="システム"}
{logger msg1="送信完了" msg2=$member.email msg3=$smarty.foreach.memberLoop.iteration}
{if $smarty.foreach.memberLoop.last}
{logger msg1="全送信完了" msg2=$smarty.foreach.memberLoop.total}
{/if}
{/foreach}
section文
{section}文は、代替のループ構造です。
基本構文
{section name="name" loop=$array}
{$array[name]}
{/section}
例
{section name="i" loop=$topics_list.list}
{logger msg1=$topics_list.list[i].subject}
{/section}
sectionのプロパティ
$smarty.section.name.first- 最初の反復でtrue$smarty.section.name.last- 最後の反復でtrue$smarty.section.name.index- 現在のインデックス$smarty.section.name.iteration- 現在の反復回数$smarty.section.name.total- 反復の総数
ループ制御
break
ループを即座に終了します。
{foreach from=$items item="item"}
{if $item.id == $target_id}
見つかりました: {$item.name}
{break}
{/if}
{/foreach}
continue
現在の反復で残りのコードをスキップし、次の反復に移動します。
{foreach from=$items item="item"}
{if $item.status == 'draft'}
{continue}
{/if}
{logger msg1=$item.title}
{/foreach}
capture文
{capture}文は、出力を表示する代わりに変数にキャプチャします。
基本構文
{capture name="varname"}
キャプチャする内容
{/capture}
実用例
{capture name="emailBody"}
{$member.name1} {$member.name2} 様
ご登録ありがとうございます。
会員IDは {$member.member_id} です。
よろしくお願いいたします。
{/capture}
{sendmail
var='result'
to=$member.email
subject='登録完了'
contents=$smarty.capture.emailBody
from="noreply@example.com"
from_nm="システム"}
コメント
単一行コメント
{* これはコメントです *}
複数行コメント
{*
これは
複数行の
コメントです
*}
変数
変数の呼び出し方
シンプルな変数
{$variable_name}
例
{assign var="greeting" value="こんにちは、世界!"}
{$greeting}
配列要素へのアクセス
ブラケット記法を使用して配列要素にアクセスします。
{$array[index]}
{$array['key']}
例
{$topics_list.list[0].subject}
{$topics_list.list[1].ymd}
{$members.list[0].email}
ハイフンを含むキーへのアクセス
Smartyの識別子(変数名・配列キー)にはハイフン(-)を使用できません。これはSmartyの言語仕様によるものです。たとえばドット記法で $request.load-debug と記述した場合、load から debug を減算する式として解釈され、意図したキーにはアクセスできません。
ハイフンを含むキーにアクセスする場合は、ブラケット記法で文字列キーとして指定します。
{$request['load-debug']}
組み合わせのアクセス例
{* ループ内でオブジェクトのプロパティにアクセス *}
{foreach from=$topics_list.list item="topics"}
{logger msg1=$topics.subject msg2=$topics.ymd}
{/foreach}
{* ネストされたオブジェクトと配列インデックス *}
{logger msg1=$topics_list.list[0].subject msg2=$topics_list.pageInfo.totalCnt}
{* ループカウンターとプロパティの組み合わせ *}
{foreach from=$members.list item="member" name="loop"}
{logger msg1=$smarty.foreach.loop.iteration msg2=$member.name1 msg3=$member.email}
{/foreach}
文字列中での変数展開
文字列の中で変数を展開するには、変数をバッククォート(`)で囲みます。
{api_internal
var='topics'
status_var='status'
endpoint="/rcms-api/3/topics/details/`$topics_id`"
method='GET'
member_id="1"}
特に、ダブルクォート文字列の中でその変数に .・[・]・-> など Smartyが識別子として扱わない文字が含まれている場合は、変数全体をバッククォートで囲む必要があります。囲まないと、ドット記法・ブラケット・アロー演算子の式が文字列中で解析できず、コンパイルエラーになります。これはSmarty標準の「埋め込み変数(embedded variables)」の構文です(Smartyマニュアル 参照)。
{* OK:単純な $ 変数をダブルクォート属性に入れる *}
{assign var="aa" value="$arg"}
{* OK:バッククォートで囲むと文字列中でも完全な式として展開される *}
{assign var="aa" value="`$arg.name`"}
{assign var="aa" value="`$item[0].title`"}
{assign var="aa" value="`$obj->prop`"}
{* OK:クォートを使わず、式を直接値として渡す *}
{assign var="aa" value=$arg.name}
{* NG:ダブルクォート文字列内の .付き変数をバッククォートで囲んでいない
— Smartyが構文エラーを出してテンプレートのコンパイルに失敗する *}
{assign var="aa" value="$arg.name"}
見落とされやすく、AIやエディタの構文ハイライトでも誤読されやすいので、ダブルクォートの属性値の中で .・[]・-> を含む変数式を書くときは、必ずバッククォート形式を使ってください。
" を含む文字列をアサインするときは、バックスラッシュでエスケープします。バッククォートによる変数展開と組み合わせることもできます。
{assign var="email" value="example@diverta.co.jp"}
{assign var="filter" value="from_mail = \"`$email`\" and receive_date >:relatively \"`$from_date`\""}
未定義の変数と配列のキー
未定義の変数や未定義の配列のキーにアクセスした場合、nullとして扱われます。
{assign_array var="member" values=""}
{append var="member" index="age" value=48}
{if $member.name === null}
$member.name is null
{else}
$member.name is not null
{/if}
{if $undefined === null}
$undefined is null
{else}
$undefined is not null
{/if}
上記の例では、$member.nameと$undefinedの両方がnullとして扱われるため、条件分岐により「$member.name is null」と「$undefined is null」が出力されます。
また、未定義の変数のキーにアクセスしようとした場合(例:{$undefined.attr})、未定義の部分で評価が打ち切られ、nullとして扱われます。これはJavaScriptのオプショナルチェーン演算子(?.)のように振る舞います。
{if $undefined.attr === null}
$undefined.attr is null
{else}
$undefined.attr is not null
{/if}
上記の例では、$undefinedが未定義のため、$undefined.attrへのアクセスは評価が打ち切られ、nullとして扱われるため、「$undefined.attr is null」が出力されます。
この安全な配列アクセスには例外があります。参照を取るタイプのモディファイア(|@sort、|@rsort、|@asort、|@arsort、|@ksort、|@krsort、|@array_push、|@array_pop、|@array_shift、|@shuffle)がチェーンの先頭に来る場合、この安全装置は適用されません。これらを使うときは、変数が定義済みであることを呼び出し側で保証してください。
変数の作り方
シンプルな代入
{assign}を使用して変数を作成または更新します。
{assign var="variable_name" value="value"}
例
{assign var="title" value="ようこそ"}
{assign var="count" value=10}
{assign var="price" value=1500}
{assign var="is_active" value=true}
既存の変数を使用
{assign var="full_name" value=$member.name1|cat:" "|cat:$member.name2}
配列の作成
{assign_array}を使用して配列を作成します。
空の配列
{assign_array var="my_array" values=""}
値を持つ配列
{assign_array var="fruits" values="apple,banana,orange"}
{assign_array var="numbers" values="1,2,3,4,5"}
カスタム区切り文字
{assign_array var="items" values="item1;item2;item3" delimiter=";"}
連想配列
{assign_array var="person" keys="name,age,email" values="John,25,john@example.com"}
オブジェクトの作成(連想配列)
{assign_array}で空のオブジェクトを作成し、{append}でプロパティを追加します。
基本的なオブジェクト作成
{assign_array var="member" values=""}
{append var="member" index="name" value="山田太郎"}
{append var="member" index="age" value=30}
{append var="member" index="email" value="yamada@example.com"}
{* プロパティへのアクセス *}
{$member.name}
{$member.age}
{$member.email}
ネストされたオブジェクト
次のようなJSONを作りたいとします。
{
"name": "山田太郎",
"address": {
"city": "東京",
"zip": "100-0001"
}
}
内側の address オブジェクトを先に作成し、外側のオブジェクトに追加します。
{* 住所オブジェクトを作成 *}
{assign_array var="address" values=""}
{append var="address" index="city" value="東京"}
{append var="address" index="zip" value="100-0001"}
{* ネストされた住所を持つ人物オブジェクトを作成 *}
{assign_array var="person" values=""}
{append var="person" index="name" value="山田太郎"}
{append var="person" index="address" value=$address}
{* ネストされたプロパティへのアクセス *}
{$person.name}
{$person.address.city}
{$person.address.zip}
配列の変更
要素の追加
{assign_array var="list" values=""}
{append var="list" value="最初の項目"}
{append var="list" value="2番目の項目"}
{append var="list" value="3番目の項目"}
Kurocoの独自拡張として、{assign}を使用して要素を追加することもできます:
{assign_array var="list" values=""}
{assign var="list." value="最初の項目"}
{assign var="list." value="2番目の項目"}
{assign var="list." value="3番目の項目"}
インデックス付きで要素を追加
{assign_array var="settings" values=""}
{append var="settings" index="theme" value="dark"}
{append var="settings" index="language" value="ja"}
{append var="settings" index="notifications" value=true}
Kurocoの独自拡張として、{assign}を使用してインデックス付きで要素を追加することもできます(ドット記法によるネストは4階層まで対応しています):
{assign_array var="settings" values=""}
{assign var="settings.theme" value="dark"}
{assign var="settings.language" value="ja"}
{assign var="settings.notifications" value=true}
実用例:APIリクエストパラメータの構築
{* API用のクエリパラメータを作成 *}
{assign_array var="method_params" values=""}
{assign_array var="method_params.topics_group_id" values="1"}
{assign_array var="request_params" values=""}
{assign var="request_params.cnt" value=20}
{assign var="request_params.pageID" value=1}
{api_method
var="topics_list"
model="Topics"
method="list"
version="1"
method_params=$method_params
request_params=$request_params}
{foreach from=$topics_list.list item="topics"}
{$topics.subject}
{/foreach}
配列を作るときのベストプラクティス
Smarty 2には配列リテラルの構文がないため、Kurocoテンプレートでは少数のヘルパープラグインを組み合わせて配列を構築します。データ形状に応じて以下のパターンから選んでください。
1. 初期化してからpush(最も一般的)
定番パターン:assign_array で空配列を宣言してから、append で1要素ずつ追加します。Kuroco内のテンプレートで最もよく見られる形です。
{assign_array var=items values=""}
{append var=items value="first"}
{append var=items value="second"}
{append var=items value=$dynamic_value}
連想配列にしたい場合は {append} に index を渡します:
{assign_array var=person values=""}
{append var=person index="name" value="Katoh"}
{append var=person index="age" value=28}
2. 区切り文字列から一発で生成
静的な値であれば、1つのタグで配列を生成できます:
{* リスト *}
{assign_array var=colors values="red,green,blue"}
{* 区切り文字を変更(値にカンマが含まれるとき) *}
{assign_array var=paths values="/a;/b;/c" delimiter=";"}
{* 連想配列(keysとvaluesの個数を一致させる) *}
{assign_array var=opts keys="host,port,ssl" values="example.com,443,true"}
3. ドット記法でネスト構造を作る
{assign} タグは、変数名にドットを含めることでネスト構造を1ステップで生成できます(4階層まで):
{assign var="user.profile.name" value="Katoh"}
{assign var="user.profile.age" value=28}
{assign var="user.roles." value="admin"} {* 末尾ドットは $user.roles へのpush *}
{assign var="user.roles." value="editor"}
結果:
user => Array
profile => Array (name=Katoh, age=28)
roles => Array ("admin", "editor")
4. イミュータブル版 — 元の配列を変更しない
{append} は var を破壊的に更新します。元の配列をそのまま残して別の配列を派生させたい場合は assign_array_set を使用します:
{assign_array_set var=updated from=$original key="status" value="done"}
{* $original は変更されず、$updated にだけキーが追加される *}
パターンの選び方
| 形状 | 推奨パターン |
|---|---|
| インデックス配列、要素が静的に決まる | {assign_array values="a,b,c"} |
| インデックス配列、ループ中に追加する | {assign_array values=""} + {append} |
| 1階層の連想配列 | {assign_array keys=... values=...} または {append index=...} |
| ネストした構造(オブジェクト風) | {assign var="a.b.c" value=...} のドット記法 |
| 元の配列を保持したまま派生させる | {assign_array_set} |
配列に関する注意点
- 配列以外の値に対するインデックスアクセスを当てにしない。 未定義の変数と配列のキー の挙動により、
{$x[0]}のアクセスは配列でなくても警告を出さずにnullを返します。意図しない値を「値あり」と誤読しやすいので、要素アクセスする前に{assign_array}で配列として明示的に初期化してください。 {append}を呼ぶ前に必ず配列として初期化する。 リストを作るときはまず{assign_array var=foo values=""}で受け側を配列として確定させてから{append}を呼んでください。未初期化の変数やスカラー値が入った変数に{append}を行うと、特に{include}をまたいだ場合に想定通りの配列にならないことがあります。
変数修飾子
変数は、パイプ(|)文字を使用して修飾子を適用できます。
基本構文
{$variable|modifier}
{$variable|modifier:parameter}
{$variable|modifier1|modifier2}
よく使われる例
{* 文字列を切り詰める *}
{$description|truncate:100}
{* 日付のフォーマット *}
{$date|date_format:"Y-m-d"}
{* 数値のフォーマット *}
{$price|number_format}
{* 複数の修飾子 *}
{$text|strip_tags|truncate:50}
配列の修飾子
配列全体を1つの値として修飾子に渡す場合は @ を付けます:
{* 配列要素数をカウント *}
{$items|@count}
{* 配列の値を取得 *}
{assign var="values" value=$array|@array_values}
{* 配列をソート *}
{assign var="sorted" value=$array|@rcms_sort}
{* JSONエンコード *}
{assign var="json" value=$array|@json_encode}
@ プレフィックスはSmarty標準の意味(「配列要素ごとに適用」ではなく「配列全体を1つの値として渡す」)であり、Kuroco独自のマーカーではありません。
モディファイアの2つの系統
Kuroco テンプレートで利用できるモディファイアには2つの系統があり、どちらに属しているかを意識しておく必要があります。
- モディファイアプラグイン —
modifier.count.php、modifier.empty.php、modifier.in_array.php、modifier.split.php、modifier.to_object.phpなどのファイル単位で実装されたモディファイアです。PHP 関数の許可リストとは無関係に動作します。例:{$arr|@count}、{$user|empty}、{$item|to_object}。利用可能なプラグインの一覧は Smartyプラグイン を参照してください。 - PHP 関数の通過呼び出し — Kuroco の
MODIFIER_FUNCS許可リストに含まれる PHP 関数は、専用のプラグインファイルが存在しなくても、そのままモディファイアとして呼び出せます。呼び出しは型検証ラッパーを経由するため、引数の型が関数シグネチャと合わない場合はnullが返り(バリデーション以外のモードでは Kuroco のエラーパイプライン経由でエラーが通知されます)、PHPのfatalエラーにはなりません。利用可能な関数の一覧は KurocoのSmartyで利用可能なPHP関数 を参照してください。
{$text|strlen} {* PHP 関数の通過呼び出し *}
{$arr|@count} {* modifier.count.php プラグインで処理される *}
{$value|intval} {* PHP 関数の通過呼び出し *}
参照を取る関数(sort、push 等)は、前述の未定義の変数と配列のキーの安全な配列アクセスの例外と連動します。
デフォルトモディファイアの抑止(|smarty:nodefaults / |raw)
グローバルにデフォルトモディファイアが設定されている環境では、|smarty:nodefaults(またはエイリアスの |raw)を付けるとその変数だけデフォルト処理を回避できます。
{$html_content|raw} {* デフォルトのエスケープ等を回避 *}
{$untrusted|smarty:nodefaults} {* 同じ意味 *}
日付処理
日付のフォーマット
date_format修飾子を使用して、日付を指定した形式でフォーマットできます。
基本構文
{$date|date_format:"format"}
例
{$date|date_format:"Y-m-d"}
{$date|date_format:"Y年m月d日"}
{$date|date_format:"H:i:s"}
日付フォーマット指定子
Kurocoのdate_formatでは、PHPのdate()関数の指定子を使用できます。フォーマット文字列に % が含まれている場合、strftime形式のコードをPHPのdate()用の書式に内部で変換してから整形されます。
PHP date()関数の指定子(推奨)
| 指定子 | 説明 | 例 |
|---|---|---|
Y | 4桁の年 | 2024 |
y | 2桁の年 | 24 |
m | 月(01-12) | 01, 12 |
n | 月(1-12) | 1, 12 |
d | 日(01-31) | 01, 31 |
j | 日(1-31) | 1, 31 |
H | 時(00-23) | 00, 23 |
h | 時(01-12) | 01, 12 |
i | 分(00-59) | 00, 59 |
s | 秒(00-59) | 00, 59 |
w | 曜日(0-6、0=日曜日) | 0, 6 |
D | 曜日の短縮形 | Mon, Sun |
l | 曜日の完全形 | Monday, Sunday |
M | 月の短縮形 | Jan, Dec |
F | 月の完全形 | January, December |
A | 午前/午後(大文字) | AM, PM |
a | 午前/午後(小文字) | am, pm |
よく使われるフォーマット例
{* YYYY-MM-DD形式 *}
{$date|date_format:"Y-m-d"}
{* YYYY年MM月DD日形式 *}
{$date|date_format:"Y年m月d日"}
{* YYYY-MM-DD HH:MM:SS形式 *}
{$date|date_format:"Y-m-d H:i:s"}
$smarty.now は現在時刻のタイムスタンプを返します。カスタム処理の先頭に以下のコードを記載すると、月曜日のみ処理が実行されるようになります。
{if $smarty.now|date_format:"D" != "Mon"}{return}{/if}
月曜日以外に実行された場合は {return} で即座に処理を終了するため、バッチ処理のスケジュールを毎日に設定しつつ、実際の処理は月曜日だけに限定する、といった使い方ができます。
strftimeの指定子
strftimeの指定子(%Y、%m、%dなど)も使用できます。% を含むフォーマット文字列は、内部でPHPのdate()用の書式に自動変換されて処理されます。
相対的な日付の処理
PHPのstrtotime関数を使用して、相対的な日付文字列を処理できます。
基本構文
{$date_string|strtotime|date_format:"format"}
例
{* 来月の最終日 *}
{assign var="day" value="last day of next month"|strtotime|date_format:"Y-m-d"}
関数呼び出し
function文
{function}文を使用して、別のカスタム処理を呼び出すことができます。
基本構文
{function name="function_name" var="result_variable" param1="value1" param2="value2"}
呼び出し元と呼び出し先は別のスコープになります。呼び出し先に値を渡すには引数として指定し、結果は{return}で返します。
例
{* 呼び出し元 *}
{function name="send_notification" var="send_result" to=$member.email subject="登録完了" message=$greeting}
{if $send_result}
メール送信に成功しました
{else}
メール送信に失敗しました
{/if}
詳細はSmartyプラグインを参照してください。
Kuroco固有のSmarty挙動と制限
{php} ブロックは使用不可
Smarty 2標準の {php}...{/php} ブロックや、テンプレート中の生の <?php ?> タグは Kuroco では使えません。Kuroco は Smarty をセキュリティモードで動作させており、テンプレートから生のPHPを実行することを許可していません。代わりに、プラグインタグ({assign}、{assign_array}、{append}、{api} など)と、許可リストにある関数呼び出しを利用してください。
$smarty.* のKuroco固有挙動
| 参照 | Kurocoでの挙動 |
|---|---|
$smarty.cookies | 無効化。常に null。Cookieはサーバー側で読み取ってください。 |
$smarty.env | 無効化。常に null。 |
$smarty.server | 参照可能ですが、DOCUMENT_ROOT、SCRIPT_FILENAME、SERVER_SOFTWARE、SERVER_ADDR、SERVER_PORT、REMOTE_PORT、REDIRECT_STATUS などの機密性の高いキーはテンプレートに渡される前に除外されます。それ以外のキーは通常通り参照できます。 |
$smarty.rcms_validate | Kuroco独自。テンプレートがバリデーションモードで実行されているときに真値となります。ドライラン実行時に副作用のある処理をスキップする用途で利用します。 |
{if !$smarty.rcms_validate}
{* バリデーション実行中はスキップ *}
{api endpoint="..." method="POST" var=resp}
{/if}
関連ドキュメント
サポート
お探しのページは見つかりましたか?解決しない場合は、問い合わせフォームからお問い合わせいただくか、Slackコミュニティにご参加ください。