Smartyの基本
2.5.x: Smarty 3 4.0.x: Smarty 4
Smartyは、開発者がプレゼンテーション(HTML/CSS)をアプリケーションロジックから分離することを可能にするPHP用テンプレートエンジンです。XOOPSはすべてのテンプレート処理にSmartyを使用し、PHPコードとHTML出力の間にきれいな分離を実現しています。
関連ドキュメント
Section titled “関連ドキュメント”- テーマ開発 - XOOPSテーマの作成
- テンプレート変数 - テンプレートで利用可能な変数
- Smarty 4マイグレーション - Smarty 3からSmarty 4へのアップグレード
Smartyとは
Section titled “Smartyとは”Smartyが提供するもの:
- 関心の分離: HTMLをテンプレートに、PHPロジックをクラスに保持
- テンプレート継承: シンプルなブロックから複雑なレイアウトを構築
- キャッシング: コンパイルされたテンプレートでパフォーマンスを向上
- 修飾子: 組み込みまたはカスタム関数で出力を変換
- セキュリティ: テンプレートがアクセスできるPHP関数を制御
XOOPSでのSmarty設定
Section titled “XOOPSでのSmarty設定”XOOPSはカスタムデリミタでSmartyを設定しています:
デフォルトSmarty: { と }XOOPSでのSmarty: <{ と }>これはテンプレート内のJavaScriptコードの競合を防ぎます。
変数はPHPからテンプレートに渡されます:
// PHP内$GLOBALS['xoopsTpl']->assign('title', 'My Page Title');$GLOBALS['xoopsTpl']->assign('count', 42);{* テンプレート内 *}<h1><{$title}></h1><p>Total items: <{$count}></p>配列アクセス
Section titled “配列アクセス”// PHP$item = [ 'id' => 1, 'title' => 'Article Title', 'author' => 'John Doe'];$GLOBALS['xoopsTpl']->assign('item', $item);{* テンプレート *}<h2><{$item.title}></h2><p>By: <{$item.author}></p>オブジェクトプロパティ
Section titled “オブジェクトプロパティ”// PHP$GLOBALS['xoopsTpl']->assign('user', $xoopsUser);{* テンプレート *}<p>Welcome, <{$user->getVar('uname')}>!</p>SmartyのコメントはHTMLに表示されません:
{* このコメントはHTML出力に表示されません *}
{* 複数行コメント もサポートされています*}If/Else文
Section titled “If/Else文”<{if $user_logged_in}> <p>お帰りなさい!</p><{elseif $is_guest}> <p>こんにちは、ゲスト!</p><{else}> <p>ログインしてください。</p><{/if}>{* 等号 *}<{if $status == 'published'}>公開<{/if}><{if $status eq 'published'}>公開<{/if}>
{* 不等号 *}<{if $count != 0}>アイテムがあります<{/if}><{if $count neq 0}>アイテムがあります<{/if}>
{* より大きい/小さい *}<{if $count > 10}>多くのアイテム<{/if}><{if $count gt 10}>多くのアイテム<{/if}><{if $count < 5}>少ないアイテム<{/if}><{if $count lt 5}>少ないアイテム<{/if}>
{* 以上/以下 *}<{if $count >= 10}>10以上<{/if}><{if $count gte 10}>10以上<{/if}><{if $count <= 5}>5以下<{/if}><{if $count lte 5}>5以下<{/if}>
{* 論理演算子 *}<{if $logged_in && $is_admin}>管理パネル<{/if}><{if $logged_in and $is_admin}>管理パネル<{/if}><{if $option1 || $option2}>1つのオプションが選択されました<{/if}><{if $option1 or $option2}>1つのオプションが選択されました<{/if}><{if !$is_banned}>アクセス許可<{/if}><{if not $is_banned}>アクセス許可<{/if}>Empty/Issetのチェック
Section titled “Empty/Issetのチェック”{* 変数が存在し、値を持っているかを確認 *}<{if $title}> <h1><{$title}></h1><{/if}>
{* 配列が空でないことを確認 *}<{if $items|@count > 0}> <ul> <{foreach $items as $item}> <li><{$item.name}></li> <{/foreach}> </ul><{/if}>
{* issetを使用 *}<{if isset($description)}> <p><{$description}></p><{/if}>Foreachループ
Section titled “Foreachループ”{* 基本的なforeach *}<ul><{foreach $items as $item}> <li><{$item.name}></li><{/foreach}></ul>
{* キー付き *}<{foreach $options as $key => $value}> <option value="<{$key}>"><{$value}></option><{/foreach}>
{* @index、@first、@lastとともに *}<{foreach $items as $item}> <{if $item@first}><ul><{/if}> <li class="item-<{$item@index}>"><{$item.name}></li> <{if $item@last}></ul><{/if}><{/foreach}>
{* 行の色を交互に *}<{foreach $rows as $row}> <tr class="<{if $row@iteration is odd}>odd<{else}>even<{/if}>"> <td><{$row.name}></td> </tr><{/foreach}>
{* 空配列の場合 *}<{foreach $items as $item}> <li><{$item.name}></li><{foreachelse}> <li>アイテムが見つかりません。</li><{/foreach}>Forループ
Section titled “Forループ”<{for $i=1 to 10}> <p>アイテム <{$i}></p><{/for}>
<{for $i=10 to 1 step -1}> <p>カウントダウン: <{$i}></p><{/for}>Whileループ
Section titled “Whileループ”<{while $count > 0}> <p><{$count}></p> <{$count = $count - 1}><{/while}>修飾子は変数出力を変換します:
文字列修飾子
Section titled “文字列修飾子”{* HTMLエスケープ(ユーザー入力には常に使用!) *}<{$title|escape}><{$title|escape:'html'}>
{* URLエンコード *}<{$url|escape:'url'}>
{* 大文字/小文字 *}<{$name|upper}><{$name|lower}><{$name|capitalize}>
{* テキストを切り詰める *}<{$content|truncate:100:'...'}>
{* HTMLタグを削除 *}<{$html|strip_tags}>
{* 置換 *}<{$text|replace:'old':'new'}>
{* 単語折り返し *}<{$text|wordwrap:80:"\n"}>
{* デフォルト値 *}<{$optional_var|default:'No value'}>{* 数値フォーマット *}<{$price|string_format:"%.2f"}><{$count|number_format}>
{* 日付フォーマット *}<{$timestamp|date_format:"%B %e, %Y"}><{$timestamp|date_format:"%Y-%m-%d %H:%M"}>{* アイテムをカウント *}<{$items|@count}> items
{* 配列を結合 *}<{$tags|@implode:', '}>
{* JSONエンコード *}<{$data|@json_encode}>修飾子をチェーン
Section titled “修飾子をチェーン”<{$content|strip_tags|truncate:200:'...'|escape}>ファイルのインクルードと挿入
Section titled “ファイルのインクルードと挿入”他のテンプレートをインクルード
Section titled “他のテンプレートをインクルード”{* テンプレートファイルをインクルード *}<{include file="db:mymodule_header.tpl"}>
{* 変数付きでインクルード *}<{include file="db:mymodule_item.tpl" item=$currentItem}>
{* 割り当てられた変数でインクルード *}<{include file="db:sidebar.tpl" assign="sidebar_content"}><div class="sidebar"><{$sidebar_content}></div>動的コンテンツを挿入
Section titled “動的コンテンツを挿入”{* 動的コンテンツ用のPHP関数を呼び出す *}<{insert name="getBanner"}>テンプレート内で変数を割り当て
Section titled “テンプレート内で変数を割り当て”{* シンプルな割り当て *}<{assign var="page_title" value="Welcome"}><{$page_title = "Welcome"}>
{* 式からの割り当て *}<{assign var="full_name" value="`$first_name` `$last_name`"}>
{* ブロックコンテンツをキャプチャ *}<{capture name="sidebar"}> <h3>サイドバー</h3> <ul> <li>Link 1</li> <li>Link 2</li> </ul><{/capture}><div class="sidebar"><{$smarty.capture.sidebar}></div>組み込みSmarty変数
Section titled “組み込みSmarty変数”$smarty変数
Section titled “$smarty変数”{* 現在のタイムスタンプ *}<{$smarty.now|date_format:"%Y-%m-%d"}>
{* リクエスト変数 *}<{$smarty.get.page}><{$smarty.post.username}><{$smarty.request.id}><{$smarty.cookies.session_id}><{$smarty.server.HTTP_HOST}>
{* 定数 *}<{$smarty.const.XOOPS_URL}>
{* 設定変数 *}<{$smarty.config.var_name}>
{* テンプレート情報 *}<{$smarty.template}><{$smarty.current_dir}>
{* Smartyバージョン *}<{$smarty.version}>
{* セクション/Foreachプロパティ *}<{$smarty.foreach.items.index}><{$smarty.foreach.items.iteration}><{$smarty.foreach.items.first}><{$smarty.foreach.items.last}>リテラルブロック
Section titled “リテラルブロック”JavaScriptで波括弧を使用する場合:
<{literal}><script> var config = { url: 'https://example.com', count: 10 }; if (config.count > 5) { console.log('Many items'); }</script><{/literal}>またはSmarty変数をJavaScript内で使用:
<script>var moduleUrl = '<{$xoops_url}>/modules/mymodule';var items = <{$items_json}>;</script>カスタム関数
Section titled “カスタム関数”XOOPSはカスタムSmarty関数を提供します:
{* XOOPSイメージURL *}<img src="<{xoImgUrl}>images/logo.png" alt="Logo">
{* XOOPSモジュールURL *}<a href="<{xoModuleUrl}>">Module Home</a>
{* アプリURL *}<a href="<{xoAppUrl 'item.php'}>?id=<{$item.id}>">View Item</a>ベストプラクティス
Section titled “ベストプラクティス”常に出力をエスケープ
Section titled “常に出力をエスケープ”{* ユーザー生成コンテンツの場合は常にエスケープ *}<p><{$user_comment|escape}></p>
{* HTMLコンテンツの場合は適切なメソッドを使用 *}<div><{$content}></div> {* コンテンツが事前にサニタイズされている場合のみ *}意味のある変数名を使用
Section titled “意味のある変数名を使用”// 良い$GLOBALS['xoopsTpl']->assign('article_title', $title);$GLOBALS['xoopsTpl']->assign('article_items', $items);
// 避けるべき$GLOBALS['xoopsTpl']->assign('t', $title);$GLOBALS['xoopsTpl']->assign('arr', $items);ロジックを最小化
Section titled “ロジックを最小化”テンプレートはプレゼンテーションに焦点を当てるべきです。複雑なロジックはPHPに移動してください:
{* テンプレートで複雑なロジックを避ける *}{* 悪い *}<{if $user && $user->getVar('level') > 5 && $user->getVar('status') == 'active' && $permissions|in_array:'edit'}>
{* 良い - PHPで計算して単純なフラグを渡す *}<{if $can_edit}>テンプレート継承を使用
Section titled “テンプレート継承を使用”一貫したレイアウトのために、テンプレート継承を使用してください(テーマ開発を参照)。
テンプレートをデバッグ
Section titled “テンプレートをデバッグ”デバッグコンソール
Section titled “デバッグコンソール”{* 割り当てられたすべての変数を表示 *}<{debug}>一時的な出力
Section titled “一時的な出力”{* 特定の変数をデバッグ *}<pre><{$variable|@print_r}></pre><pre><{$variable|@var_export}></pre>一般的なXOOPSテンプレートパターン
Section titled “一般的なXOOPSテンプレートパターン”モジュールテンプレート構造
Section titled “モジュールテンプレート構造”{* モジュールヘッダー *}<div class="mymodule"> <h2><{$module_name}></h2>
{* パンくずリスト *} <{if $breadcrumb}> <nav class="breadcrumb"> <{foreach $breadcrumb as $crumb}> <{if $crumb@last}> <span><{$crumb.title}></span> <{else}> <a href="<{$crumb.link}>"><{$crumb.title}></a> » <{/if}> <{/foreach}> </nav> <{/if}>
{* コンテンツ *} <div class="content"> <{$content}> </div></div>ページネーション
Section titled “ページネーション”<{if $page_nav}><div class="pagination"> <{$page_nav}></div><{/if}>フォーム表示
Section titled “フォーム表示”<{if $form}><div class="form-container"> <{$form}></div><{/if}>#smarty #テンプレート #xoops #フロントエンド #テンプレートエンジン