Smartyのテンプレートをテキストデータとしてデータベースに保存し、webサイトで記事ページに飛んだ時に、それをSmartyのテンプレートに読み込ませて表示させる処理を実装しましたので説明していきます(CakePHP v.3.4.4)。
ざっくり言うと、テンプレートファイルの中で、文字列からテンプレートをレンダリングさせるやり方です。
CakePHPでSmartyを使えるようになっている前提で進めていきます。
CakePHPでSmartyを使えるようにするのに、こちらの情報を参考にさせていただきました。
Smartyテンプレートを準備する
Articlesテーブルにデータを保存します。
「body」カラムにテンプレートを、「title」カラムに記事タイトルを保存します。
テンプレートとして以下のものを用意しました。
<ul>
<li><a href="/top">HOME</a></li>
<li><a>{$title}</a></li> <!-- ←Smartyの構文が入ってます -->
</ul>
<main>
<section>
<h2>{$title}</h2>
<div>
</div>
</section>
</main>
<div>
<p><a href="/top">TOPページに戻る</a></p>
</div>
controllerで記事を取得しview変数にセット
【ArticlesController.php】
一覧ページから記事IDをもらって、その記事IDのデータを取得しています。
「body」(記事データ本文)と「title」(記事タイトル)をview変数に渡しています。
public function view($id)
{
$this->loadModel('Articles');
$article = $this->Articles->get($id);
$body = $article['body']; //←記事本文(先ほど登録したテンプレート)
$title = $article['title']; //←記事タイトル
$this->set(compact('body','title'));
}
記事を表示するtplファイルを準備
view.tplファイルに以下の1行を入れる
【view.tpl】
{include file="string:$body"}
「$body」はcontrollerでview変数にセットされたものです。
この{include file=”string:$body”}によって、
「$body」にセットした文字列からテンプレートをレンダリングすることができます。
さらには、先ほどのテンプレートの中の{$title}の箇所もSmartyの構文として解釈されるので、データベースから取得した記事タイトルが挿入されます。
ここまでの実装で、ArticlesControllerのviewアクションに記事IDを渡してあげれば、対象の記事の表示させることができます。
今回は簡単に見せるために、データベースから取得したテンプレートの中にそのタイトルを入れるという意味のなさそうな例文となってしまいましたが、{foreach}や{date_format}などを使用したテンプレートでも、ファイルから読み込むのと同じように処理されます。
私が最初に間違っていたこと
先ほど説明した手順で、view.tplファイルに
{include file=”string:$body”}を入れなければならないとお伝えしましたが、
最初はただ{$body}と記述しておりました。
基本的なhtmlの要素は表示はされますが、Smartyの構文である{$title}の部分は、レンダリングされずに文字列として画面に表示されてしまいます。
本来「記事タイトル」を表示したいところに{$title}が表示される、、、。
(今回の答えに行き着くまでに結構迷走しました、、、。)
まとめ
Smartyのテンプレートの中で、文字列からテンプレートをレンダリングするには
{include file=”string:$template_string”}
「$template_string」はテンプレートにしたい文字列
あまり使用する機会はないかもしれませんが、文字列からテンプレートを読み込む情報がなかなかありませんでしたので記事にいたしました。
参考文献
飲食業界からIT業界に転身してきて現在2年目です。PHPの経験がメインとなります。これまで自分がPHPを扱ってきた上で、モヤモヤしてきたことをメインに記事にしていきますのでよろしくお願いいたします。