TacmicCMSにおけるPHPロジック、Smartyテンプレート、MariaDBデータの3層分離と基本アーキテクチャを学びます。
TacmicCMSは、堅牢なPHPバックエンドと高速なMariaDBデータベース、そして柔軟なSmartyテンプレートエンジンが有機的に結合したオープンソースCMSです。
TacmicCMSは、プログラムコード(PHP)の中にHTMLを直接混在させるのではなく、責務ごとに明確に分離されています。
この分離により、デザイン担当者とプログラム開発者が互いの作業を妨げることなく、安全かつ効率的にサイト構築やモジュール開発を行うことができます。
訪問者がブラウザからURLにアクセスした際、TacmicCMSは以下のステップを経て画面を生成・出力します。
mainfile.php のロード: データベース接続、サイトURL(XOOPS_URL)、物理パス(XOOPS_ROOT_PATH / XOOPS_TRUST_PATH)、セキュリティチェックを初期化。header.php のロード: セッション開始、ログインユーザー認証、有効なテーマ決定、Smartyテンプレートエンジン($xoopsTpl)のインスタンス化、配置されたブロックのデータ取得。$xoopsTpl->assign() でSmartyへ引き渡し。theme.html)を結合し、Smartyタグを高速なPHPコードへとコンパイル(templates_c にキャッシュ保存)。footer.php の出力: フッターブロックの処理、デバッグ情報の収集、最終的なHTMLをブラウザへ送出。templates_c フォルダに保存します。2回目以降のアクセスではこのコンパイル済みPHPが直接実行されるため、ネイティブPHPとほぼ同等の超高速動作を実現しています。PHPからSmartyへデータを渡すassignメソッドと、テンプレート定義ファイルicms_version.phpの役割を解説します。
PHP側で取得・加工したデータは、$xoopsTpl->assign() を呼び出してSmarty変数として登録します。
// 単一の値(文字列や数値)
$xoopsTpl->assign('page_title', '新着ニュース一覧');
$xoopsTpl->assign('item_count', 42);
// 連想配列(レコード1件分)
$topic = [
'id' => 101,
'title' => 'TacmicCMS 2.0 リリース!',
'date' => '2026-11-02'
];
$xoopsTpl->assign('topic', $topic);
// 多次元配列(ループ表示用のリスト)
$articles = [];
while ($row = $db->fetchArray($result)) {
$articles[] = $row;
}
$xoopsTpl->assign('articles', $articles);
モジュールのメイン画面を表示する場合、header.php をインクルードする前に $xoopsOption['template_main'] を指定します。
<?php
include_once "header.php";
// このページで使用するSmartyテンプレートファイル名を指定
$xoopsOption['template_main'] = "d3news_index.html";
include_once XOOPS_ROOT_PATH . "/header.php";
// ... モジュールのロジック処理 ...
include_once XOOPS_ROOT_PATH . "/footer.php";
?>
モジュール内で使用するテンプレートは、モジュールの定義ファイル icms_version.php(または xoops_version.php)に宣言しておく必要があります。管理画面でのテンプレートセット管理(ALTSYS等)やDBへの取り込みに必須です。
$modversion['templates'][] = [
'file' => 'd3news_index.html',
'description' => 'ニュース一覧トップページ'
];
$modversion['templates'][] = [
'file' => 'd3news_article.html',
'description' => 'ニュース記事詳細ページ'
];
TacmicCMSにおけるSmartyデリミタ、コメント記法、波括弧競合を防ぐリテラルタグの正しい使い方を習得します。
Smartyテンプレートは、通常のHTMLの中に デリミタ(区切り記号) で囲まれたSmartyタグを埋め込むことで動作します。
TacmicCMSでは、Web標準のHTML5/CSS/JavaScriptと安全に共存できるように設計されたデリミタルールが採用されています。
TacmicCMS推奨デリミタ <{ }> とコメント構文 <{* *}> の安全性について詳解します。
<{ と }>標準的なSmartyでは { ... }(波括弧)がデリミタとして使われることが多いですが、TacmicCMSおよびXOOPS/ImpressCMS系では <{ と }> が標準採用されています。
<{ ... }> を使うのか?{ font-size: 14px; } や function() { ... } のように波括弧が頻繁に登場します。デリミタが単なる { } だと、SmartyがCSSやJSの波括弧を変数や関数と誤認してパースエラー(構文エラー)を起こしてしまいます。<{ ... }> を使うことで、CSSやJavaScriptとの不要な衝突を自然に回避できます。
<{* ... *}>テンプレート内に制作メモやロジックの説明を残したい場合は、Smartyコメントタグを使用します。
<{* ここは管理者向け専用エリアです。一般ユーザーには非表示 *}>
<{if $icms_isadmin}>
<div class="admin-panel">管理用リンク</div>
<{/if}>
| コメント種別 | 書き方 | HTMLソースに出力されるか? | 用途・安全性 |
|---|---|---|---|
| Smartyコメント | <{* コメント内容 *}> |
一切出力されない | 社内メモ、仕様解説、非公開コード。ブラウザで見られないため安全。 |
| HTMLコメント | <!-- コメント内容 --> |
ブラウザにそのまま届く | 「ページのソースを表示」で見えてしまうため、機密情報や内部仕様は書かないこと。 |
JavaScript、jQuery、CSS、JSON-LD構造化データを安全に埋め込むためのテクニックを解説します。
<{literal}> と <{/literal}> で囲まれたブロックの中身は、Smartyエンジンによる解釈が完全に停止し、文字通り(Literal)そのまま出力されます。
<{literal}>
<script>
document.addEventListener("DOMContentLoaded", function() {
const btn = document.querySelector("#submit-btn");
btn.addEventListener("click", function(e) {
alert("送信処理を実行します");
});
});
</script>
<{/literal}>
Google検索結果のリッチスニペットで必須となるJSON-LDは波括弧が連続するため、必ず <{literal}> を活用します。
<script type="application/ld+json">
<{literal}>
{
"@context": "https://schema.org",
"@type": "Article",
"headline": <{/literal}>"<{$topic.title|escape:'javascript'}>"<{literal}>,
"datePublished": <{/literal}>"<{$topic.published|date_format:'%Y-%m-%d'}>"<{literal}>
}
<{/literal}>
</script>
<{/literal}> を閉じ、Smarty変数 <{$topic.title}> を出力した直後に再び <{literal}> を再開することで、複雑なJSONの中でも安全に変数を埋め込むことができます。
テンプレート変数の参照法、スーパーグローバル変数、TacmicCMSコア提供変数、D3モジュール変数を徹底解説します。
Smartyにおける変数は先頭にドル記号 $ を付けます。PHPから渡されたデータだけでなく、スーパーグローバル変数やTacmicCMSが提供するコア変数にアクセスできます。
スカラー値、連想配列、添字配列、オブジェクトプロパティ・メソッドの参照記法を整理します。
| Smartyの記法 | PHPでの相当コード | 説明 |
|---|---|---|
<{$sitename}> |
$sitename |
文字列、数値などの単純なスカラー変数を出力 |
<{$user.name}> |
$user['name'] |
連想配列のキー 'name' の値を参照(ドット構文) |
<{$list[0]}> |
$list[0] |
数値インデックス配列の1番目の要素を参照 |
<{$item.category.title}> |
$item['category']['title'] |
階層化された多次元連想配列を連続してドットで参照 |
<{$article->title}> |
$article->title |
オブジェクトのパブリックプロパティを参照 |
<{$article->getTitle()}> |
$article->getTitle() |
オブジェクトのメソッドを実行して返り値を参照 |
$smarty.get, $smarty.post, $smarty.const, $smarty.now などの予約変数を網羅します。
$smarty.*)PHP側でわざわざ assign しなくても、Smartyが初めから用意している特別な予約変数です。
| Smarty予約変数 | 対応するPHPグローバル | 解説・具体例 |
|---|---|---|
<{$smarty.get.id}> |
$_GET['id'] |
URLクエリパラメータ(例: ?id=5)の値を取得 |
<{$smarty.post.keyword}> |
$_POST['keyword'] |
フォームからPOST送信されたパラメータを取得 |
<{$smarty.session.userid}> |
$_SESSION['userid'] |
現在のセッション変数に保持されている値を取得 |
<{$smarty.cookies.theme}> |
$_COOKIE['theme'] |
クライアントCookieの値を取得 |
<{$smarty.server.REQUEST_URI}> |
$_SERVER['REQUEST_URI'] |
現在のアクセスパス・URLパスを取得 |
<{$smarty.now}> |
time() |
現在のUNIXタイムスタンプ(後述の date_format 修飾子と併用) |
<{$smarty.const.XOOPS_URL}> |
XOOPS_URL |
PHPの define() で定義された定数を直接参照 |
© <{$smarty.now|date_format:"%Y"}> TacmicCMS とテンプレートに書いておけば、毎年手動でテーマの年号を書き換える手間がゼロになります!
テーマやブロックで常に利用可能なシステム定義グローバル変数の完全一覧です。
theme.html)およびブロックで利用できる主要変数| 変数名 | 型 | 内容・用途 |
|---|---|---|
<{$icms_sitename}> |
string | 一般設定で登録された「サイト名」 |
<{$icms_slogan}> |
string | 一般設定で登録された「サイトのスローガン」 |
<{$icms_pagetitle}> |
string | 現在のページタイトル(<title> タグで使用) |
<{$icms_url}> / <{$xoops_url}> |
string | サイトのルートURL(例: http://tcms.local) |
<{$icms_imageurl}> |
string | 現在適用されているテーマのURL(例: /themes/tacmic/) |
<{$icms_themecss}> |
string | テーマ標準CSSのURL(style.css) |
<{$xoops_contents}> |
string | 最重要:各モジュールがレンダリングしたメインHTMLが出力される位置 |
<{$xoops_module_header}> |
string | モジュールが必要とするCSSやJavaScript(<head> 内に必須) |
<{$icms_isuser}> |
bool | ログイン中の一般ユーザーなら true |
<{$icms_isadmin}> |
bool | 管理者グループに所属しているなら true |
<{$icms_uname}> |
string | ログインユーザーのアカウント名(ハンドル名) |
<{$icms_breadcrumbs}> |
array | パンくずナビゲーション用の階層リンク配列 |
$mydirname や $mod_url など、D3モジュール複製時に活躍する必須変数を解説します。
<{$mydirname}>D3(Duplicatable V3)アーキテクチャでは、1つのモジュール(例: d3chapter)をフォルダ名を変えて複製(例: smartyset, manual, book2)し、複数共存させることができます。
そのため、テンプレート内ではモジュールディレクトリ名を絶対にハードコードせず、必ず <{$mydirname}> を使用します。
<{* 悪い例:フォルダ名が固定されているため複製するとリンクが壊れる *}>
<a href="<{$xoops_url}>/m/d3chapter/content.php?lid=1">第1章へ</a>
<{* 良い例:現在のモジュール名が自動展開されるため完全にポータブル *}>
<a href="<{$mydirurl}>/content.php?lid=1">第1章へ</a>
<img src="<{$xoops_url}>/m/<{$mydirname}>/images/icon.png" alt="アイコン" />
<{$mydirname}>: 現在実行中のモジュールのディレクトリ名(例: smartyset)<{$mydirurl}> / <{$mod_url}>: 現在のモジュールのWebアクセスURL<{$mod_config}>: モジュールの一般設定パラメータ配列(<{$mod_config.items_per_page}> 等)Smartyが提供する文字列操作、日付変換、数値フォーマット、XSS対策エスケープ修飾子を実例付きで完全網羅します。
変数の修飾子(Modifier)とは、出力する直前に変数へ適用するフィルタ機能です。パイプ記号 | を使って指定します。
<{$変数名|修飾子:パラメータ1:パラメータ2}>
lower, upper, capitalize, cat, truncate, strip_tags などの実用例です。
| 修飾子 | 構文例 | 機能と出力結果の例 |
|---|---|---|
| lower | <{$str|lower}> |
英字をすべて小文字に変換(HELLO → hello) |
| upper | <{$str|upper}> |
英字をすべて大文字に変換(hello → HELLO) |
| capitalize | <{$str|capitalize}> |
単語の先頭を大文字化(tacmic cms → Tacmic Cms) |
| cat | <{$name|cat:" 様"}> |
文字列の末尾に指定テキストを連結(久岡 → 久岡 様) |
| truncate | <{$text|truncate:60:"..."}> |
指定文字数で丸め、末尾に省略記号を付与(一覧サマリー表示に多用) |
| strip_tags | <{$html|strip_tags}> |
HTMLタグ(<p>等)をすべて除去して純粋なテキストのみを抽出 |
| replace | <{$text|replace:"XOOPS":"TacmicCMS"}> |
指定文字列を別の文字列へ置換 |
date_format, number_format, string_format の詳細なフォーマット指定子を解説します。
date_format(日付・時刻フォーマット)UNIXタイムスタンプを任意の年月日時分秒形式に整形します。CMSで最も頻繁に使われる修飾子です。
<{* 年月日と時分を表示 *}>
<{$article.posted|date_format:"%Y年%m月%d日 %H:%M"}>
<{* 出力例: 2026年11月02日 16:30 *}>
<{* ハイフン区切りの短い日付 *}>
<{$article.posted|date_format:"%Y-%m-%d"}>
<{* 出力例: 2026-11-02 *}>
| 指定子 | 説明 | 出力例 |
|---|---|---|
%Y | 4桁の西暦 | 2026 |
%m | 2桁の月(01〜12) | 11 |
%d | 2桁の日(01〜31) | 02 |
%H | 24時間制の時(00〜23) | 16 |
%M | 2桁の分(00〜59) | 30 |
%S | 2桁の秒(00〜59) | 00 |
number_format(数値・金額のカンマ区切り)<span class="price"><{$product.price|number_format}> 円</span>
<{* 2300000 → 2,300,000 円 *}>
string_format(ゼロ埋めフォーマット)<{* 4桁ゼロパディング(コード番号やID管理に便利) *}>
<{$user.id|string_format:"%04d"}>
<{* 5 → 0005 *}>
XSS脆弱性を防ぐescape、空データフォールバックdefault、改行反映nl2brの安全な併用パターンです。
escape(HTML/JavaScriptエスケープ:XSS対策)外部からの入力値、投稿記事のタイトル、ユーザーのコメントなどを出力する際は、クロスサイトスクリプティング(XSS)を防ぐために必ず escape を通します。
<{* HTML特殊文字(< > & ")を安全にエンコード *}>
<h3><{$comment.title|escape}></h3>
<{* inputタグのvalue属性に安全に埋め込む場合 *}>
<input type="text" name="uname" value="<{$user.uname|escape:'html'}>" />
<{* JavaScript文字列の中に埋め込む場合 *}>
<script>
const userTitle = "<{$user.title|escape:'javascript'}>";
</script>
default(未定義・空値時の代替テキスト)変数が null、空文字、未定義の場合に出力するデフォルト値を指定します。
<{* 説明文が空なら「説明はありません」を表示 *}>
<p><{$item.description|default:"説明はありません"}></p>
<{* ユーザーのアバター画像が未登録なら共通デフォルト画像を表示 *}>
<img src="<{$user.avatar|default:'/images/default_avatar.png'}>" alt="アバター" />
修飾子は左から順にいくつでもパイプ | で繋げることができます。
<{* 1. HTMLエスケープして安全にした後、2. 改行を <br /> に変換する最強パターン *}>
<div class="body"><{$post.comment|escape|nl2br}></div>
<{* 1. HTMLタグを除去し、2. 80文字で省略し、3. 安全にエスケープ *}>
<p class="summary"><{$article.body|strip_tags|truncate:80:"..."|escape}></p>
条件分岐 if/elseif/else、繰り返し foreach とその高度なループプロパティ、テンプレート分割 include を学びます。
Smartyには、PHPのように条件分岐や繰り返し処理、外部テンプレートの分割インクルードを行う組み込み関数が用意されています。
完全な比較演算子・論理演算子対応表と、安全な値判定のベストプラクティスです。
<{if $role == 'admin'}>
<span class="badge admin">管理者</span>
<{elseif $role == 'editor'}>
<span class="badge editor">編集者</span>
<{else}>
<span class="badge guest">一般ユーザー</span>
<{/if}>
| 記号 | 英語代替 | 構文例 | 意味 |
|---|---|---|---|
== | eq | $a == $b | 等しい |
!= | ne, neq | $a != $b | 等しくない |
> | gt | $a > $b | より大きい |
< | lt | $a < $b | より小さい |
>= | gte, ge | $a >= $b | 以上 |
<= | lte, le | $a <= $b | 以下 |
! | not | !$is_active | 否定(〜ではない) |
&& | and | $a && $b | 論理積(かつ) |
|| | or | $a || $b | 論理和(または) |
is even | - | $num is even | 偶数である |
is odd | - | $num is odd | 奇数である |
foreachの基本、name属性を使ったループ番号iterationやfirst/lastプロパティ、foreachelseを完全習得。
foreachelse配列の全要素をループ処理します。配列が空(0件)のときのために <{foreachelse}> を用意しておくと便利です。
<{foreach from=$articles item="article" key="id"}>
<div class="article-card">
<h4><{$article.title}></h4>
<p><{$article.summary}></p>
</div>
<{foreachelse}>
<p class="no-data">現在公開されている記事はありません。</p>
<{/foreach}>
name 属性の指定)name="myloop" のように名前を付けると、ループの回数や最初/最後の判定が可能になります。
<ul>
<{foreach from=$ranking item="rank" name="rankLoop"}>
<li class="<{if $smarty.foreach.rankLoop.first}>top-winner<{/if}>">
第<{$smarty.foreach.rankLoop.iteration}>位: <{$rank.name}>
(全<{$smarty.foreach.rankLoop.total}>人中)
</li>
<{/foreach}>
</ul>
| プロパティ | 値 | 説明 |
|---|---|---|
.iteration |
1, 2, 3... | 1から始まる現在のループ番号(順位表示や番号付けに最適) |
.index |
0, 1, 2... | 0から始まる現在のインデックス値 |
.first |
true / false | ループの最初の要素なら true |
.last |
true / false | ループの最後の要素なら true(区切り線の制御に便利) |
.total |
int | ループする要素の総件数 |
include file="db:..." によるパーツ共通化とパラメータ引き渡しを解説します。
<{include}>ページネーションバー、カードUI、ソーシャルシェアボタンなど、複数箇所で使い回したい部品はサブテンプレートとして切り出し、include 関数で読み込みます。
<{* DBテンプレートセットに登録されたサブテンプレートをインクルード *}>
<{include file="db:d3news_article_card.html" article=$one_article}>
db: プレフィックスの秘密file="db:ファイル名" と指定すると、TacmicCMSはデータベース(tplfile テーブル)に登録されたテンプレートセット(ALTSYS等でカスタマイズ可能)を優先的に読み込みます。これにより、実ファイルを触らずに管理画面から安全にデザインを上書きできます。
assign, cycle, counter, html_options, resized_image など便利なテンプレート関数を紹介します。
Smarty本体およびTacmicCMSには、テンプレートの記述を簡潔にし、デザインの表現力を高めるカスタム関数プラグインが多数用意されています。
テンプレート内での変数再定義、テーブル行のストライプ配色、カウンタ関数の使い方です。
assign(テンプレート内で変数を定義・変更)<{* テンプレート内で一時的なフラグや値をセット *}>
<{assign var="has_special_discount" value=true}>
<{assign var="banner_class" value="promo-highlight"}>
<{if $has_special_discount}>
<div class="<{$banner_class}>">特別割引セール開催中!</div>
<{/if}>
cycle(偶数・奇数のストライプ背景)ループ内で呼び出すたびに、指定した値を交互に出力します。
<table>
<{foreach from=$users item="u"}>
<tr class="<{cycle values='odd,even'}>">
<td><{$u.id}></td>
<td><{$u.uname}></td>
</tr>
<{/foreach}>
</table>
counter(ループ内番号インクリメント)<{* 1から始まり、呼ぶたびに1ずつ増える *}>
<span class="badge">No. <{counter start=1 skip=1}></span>
セレクトボックスやラジオボタンを連想配列から一発生成するSmarty標準関数の活用法です。
html_options(セレクトボックスの自動生成)PHPから渡された連想配列から、<option> タグを一括自動生成します。現在選択されている値(selected)も自動で判定されます。
<select name="prefecture" id="prefecture">
<{html_options options=$pref_list selected=$current_pref_id}>
</select>
html_radios(ラジオボタングループの自動生成)<div class="radio-group">
<{html_radios name="gender" options=$gender_options selected=$current_gender separator=" "}>
</div>
TacmicCMSコアに搭載された高速リサイズ&WebP対応画像プラグインの使い方を解説します。
resized_image プラグイン(画像リサイズ&キャッシュ)アップロードされた大きな画像ファイル(JPEG/PNG等)を、テンプレート上で指定したピクセルサイズに自動縮小し、キャッシュディレクトリへ出力するTacmicCMS独自プラグインです。
<{* 幅300px・高さ200pxに自動リサイズして表示 *}>
<img src="<{resized_image file=$article.image_path width=300 height=200}>" alt="<{$article.title|escape}>" />
public/cache に保存。サイト全体のデザインを統括するtheme.htmlの構造、必須タグ、3カラムから1カラムへのレスポンシブ制御を解説します。
モジュールのコンテンツは、最終的にテーマ(themes/テーマ名/theme.html)の骨格の中に流し込まれます。美しいテーマを設計するための基本ルールを学びます。
HTML5 DOCTYPE、viewport、module_header、xoops_contentsの配置ルールです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<title><{if $icms_pagetitle}><{$icms_pagetitle}> : <{/if}><{$icms_sitename}></title>
<link rel="stylesheet" href="<{$icms_imageurl}>style.css">
<{* モジュールが要求するCSS・JSを出力(必須!) *}>
<{$xoops_module_header}>
</head>
<body>
<header class="site-header">
<h1><a href="<{$icms_url}>/"><{$icms_sitename}></a></h1>
</header>
<main class="site-main">
<{* 各モジュールが生成したメインHTMLがここに挿入される(超重要!) *}>
<{$xoops_contents}>
</main>
<footer class="site-footer">
<p>© <{$smarty.now|date_format:'%Y'}> <{$icms_sitename}></p>
</footer>
</body>
</html>
サイドバーブロックの表示判定フラグと、CSSグリッド/フレックスボックスとの連携方法です。
管理画面の「ブロック管理」でサイドバーにブロックが配置されているかどうかは、$xoops_showlblock(左)や $xoops_showrblock(右)の真偽値で自動判定できます。
<div class="layout-container <{if $xoops_showlblock}>has-left-sidebar<{else}>no-sidebar<{/if}>">
<{* 左サイドバーが存在するときだけ描画 *}>
<{if $xoops_showlblock}>
<aside class="left-sidebar">
<{foreach item=block from=$xoops_lblocks}>
<section class="block-box">
<h3 class="block-title"><{$block.title}></h3>
<div class="block-content"><{$block.content}></div>
</section>
<{/foreach}>
</aside>
<{/if}>
<article class="main-content">
<{$xoops_contents}>
</article>
</div>
D3テンプレートの3段階優先順位メカニズムと、ALTSYSを使った安全なDBテンプレートカスタマイズ手順を解説します。
D3モジュールの最大の特徴は、サーバー上の実ファイルを一切書き換えることなく、管理画面(ALTSYS)からデータベース上でテンプレートを安全にカスタマイズできる点にあります。
DBテンプレート(選択中テーマ)→ defaultセット → trust_path実ファイルの探索フローです。
TacmicCMSがD3モジュールのテンプレートを読み込む際、以下の優先順位で探索します。
themes/tacmic/ を使用中なら、DB内の tacmic テンプレートセット。default セット。trust_path 内の物理テンプレートファイルtrust_path/modules/モジュール名/templates/ のファイルが直接参照されます。trust_path 内のファイルが更新されても、管理者がDB上でカスタマイズしたテンプレート(第1優先)はデータベースに安全に保持されるため、上書きされてデザインが消える心配がありません。
ALTSYSのテンプレート管理を使った安全な複製・編集・デバッグ手順をステップバイステップで解説します。
default セットはベースとなる基本セットのため、直接編集せず、使用しているテーマ名(例: tacmic)のセットへ 「複製」 します。d3news_index.html)の 「編集」 をクリック。templates_c)が自動で再生成され、即座にサイトのデザインへ反映されます。PHP 8.2〜8.5で厳格化された未定義配列キー警告や未定義変数のエラーを出さないモダンテンプレート手法です。
PHP 8.2以降、特にPHP 8.5環境では、未定義の変数や配列キーへのアクセスに対する警告(Warning)が厳格化されました。エラーを出さない安全なSmartyコーディング作法を学びます。
empty(), isset(), default修飾子を活用した堅牢な条件判定パターン集です。
古いテンプレートでよく見られた以下の書き方は、PHP 8.5環境で Undefined array key 警告の原因となります。
<{* 危険な例:$user['avatar'] が未定義だと Warning が発生する *}>
<{if $user.avatar != ''}>
<img src="<{$user.avatar}>" />
<{/if}>
<{* 安全な例 1:!empty() を使用(未定義でも警告が出ない) *}>
<{if !empty($user.avatar)}>
<img src="<{$user.avatar}>" />
<{/if}>
<{* 安全な例 2:default 修飾子を併用する *}>
<img src="<{$user.avatar|default:'/images/no_image.png'}>" />
{if !empty($data.key)} で判定する。|default:'' を添えることで、NULLや未定義を空文字に安全フォールバックする。{foreachelse} を活用し、空配列時の例外表示をスマートに行う。Webセキュリティの基本である出力エスケープのベストプラクティス総まとめです。
動的なWebサイトにおいて、セキュリティの最前線となるのがテンプレートです。以下の原則を徹底しましょう。
|escape を通す:
掲示板、コメント、プロフィール、お問い合わせフォームなど、訪問者が入力した文字列を出力する箇所は例外なくエスケープします。|escape:'url' を通す:
<a href="search.php?q=<{$keyword|escape:'url'}>"> のように属性値に埋め込む場合はURLエンコードを行います。|escape|nl2br)に統一します。| 1 | 第1部:TacmicCMSの構造とテンプレートの役割 | Publish | 1620 bytes | 2026-11-02 16:15 | by admin | |
| 1 - 1 | TacmicCMSの全体構造とアーキテクチャ | Publish | 2171 bytes | 2026-11-02 16:29 | by サイト管理人 | |
| 1 - 2 | モジュール開発とテンプレートの関係 | Publish | 2223 bytes | 2026-11-02 16:15 | by admin | |
| 2 | 第2部:Smartyテンプレートの基本構文と作法 | Publish | 354 bytes | 2026-11-02 16:15 | by admin | |
| 2 - 1 | デリミタ(区切り文字)と基本ルール | Publish | 3275 bytes | 2026-11-02 16:15 | by admin | |
| 2 - 2 | リテラルタグ <{literal}> の重要性と活用法 | Publish | 1881 bytes | 2026-11-02 16:15 | by admin | |
| 3 | 第3部:変数(Variables)とスコープ完全ガイド | Publish | 252 bytes | 2026-11-02 16:15 | by admin | |
| 3 - 1 | テンプレート変数の基本とデータ構造の参照法 | Publish | 2748 bytes | 2026-11-02 16:15 | by admin | |
| 3 - 2 | Smarty予約変数(スーパーグローバルと環境変数) | Publish | 3752 bytes | 2026-11-02 16:15 | by admin | |
| 3 - 3 | TacmicCMS / ImpressCMS コア提供グローバル変数一覧 | Publish | 4791 bytes | 2026-11-02 16:15 | by admin | |
| 3 - 4 | D3モジュール特有の変数と環境変数 | Publish | 1680 bytes | 2026-11-02 16:15 | by admin | |
| 4 | 第4部:変数の修飾子(Modifiers)徹底解説 | Publish | 308 bytes | 2026-11-02 16:15 | by admin | |
| 4 - 1 | 文字列操作・整形修飾子 | Publish | 3224 bytes | 2026-11-02 16:15 | by admin | |
| 4 - 2 | 日付・数値・フォーマット修飾子 | Publish | 2893 bytes | 2026-11-02 16:15 | by admin | |
| 4 - 3 | セキュリティ・安全性修飾子(escape, default, nl2br) | Publish | 2066 bytes | 2026-11-02 16:15 | by admin | |
| 5 | 第5部:制御構文と組み込み関数(Built-in Functions) | Publish | 194 bytes | 2026-11-02 16:15 | by admin | |
| 5 - 1 | 条件分岐(if, elseif, else)と演算子 | Publish | 4456 bytes | 2026-11-02 16:15 | by admin | |
| 5 - 2 | 繰り返し処理(foreach)とループプロパティ | Publish | 3335 bytes | 2026-11-02 16:15 | by admin | |
| 5 - 3 | テンプレート分割とインクルード(include) | Publish | 1132 bytes | 2026-11-02 16:15 | by admin | |
| 6 | 第6部:TacmicCMSカスタム関数・プラグイン | Publish | 209 bytes | 2026-11-02 16:15 | by admin | |
| 6 - 1 | 変数操作と装飾プラグイン(assign, cycle, counter) | Publish | 1225 bytes | 2026-11-02 16:15 | by admin | |
| 6 - 2 | フォーム生成ヘルパー(html_options, html_radios) | Publish | 779 bytes | 2026-11-02 16:15 | by admin | |
| 6 - 3 | TacmicCMS専用関数(resized_image) | Publish | 879 bytes | 2026-11-02 16:15 | by admin | |
| 7 | 第7部:テーマ(theme.html)設計とレスポンシブ化 | Publish | 246 bytes | 2026-11-02 16:15 | by admin | |
| 7 - 1 | theme.html の基本スケルトンと必須要素 | Publish | 1230 bytes | 2026-11-02 16:15 | by admin | |
| 7 - 2 | ブロック配置とレイアウト制御(カラムレイアウト) | Publish | 1135 bytes | 2026-11-02 16:15 | by admin | |
| 8 | 第8部:D3モジュールのテンプレート管理とカスタマイズ(ALTSYS連携) | Publish | 265 bytes | 2026-11-02 16:15 | by admin | |
| 8 - 1 | D3テンプレートの基本構造(3段階の優先順位) | Publish | 1526 bytes | 2026-11-02 16:15 | by admin | |
| 8 - 2 | ALTSYSでのテンプレート複製と編集テクニック | Publish | 871 bytes | 2026-11-02 16:15 | by admin | |
| 9 | 第9部:PHP 8.5 時代の安全なSmartyコーディング作法 | Publish | 257 bytes | 2026-11-02 16:15 | by admin | |
| 9 - 1 | Undefinedエラー(Warning/Fatal)を出さない書き方 | Publish | 1308 bytes | 2026-11-02 16:15 | by admin | |
| 9 - 2 | XSS防止とエスケープポリシー(総まとめ) | Publish | 1539 bytes | 2026-11-02 16:15 | by admin |