Smartyの使い方

Smartyとは

Smartyとは、PHP上で動作するテンプレートエンジンです。PHPはHTML上に記述することができるスクリプトですが、それはPHPのメリットでもあると同時にデメリットにもなり得ます。小規模なサイトでデザイン、HTMLコーディング、PHPプログラミングまで一人で行うのであれば、HTML上に記述することができるということは大変なメリットです。ただし、大規模なサイトなどでHTMLコーディング、PHPプログラミングとそれぞれの作業を異なる担当者が行う場合は、非常に効率が悪くなります。HTMLコーディング担当にとっては、PHPのコードが記述されているコードは非常にわかりにくくなってしまうばかりか、HTMLコーディング担当作業中PHPプログラミング担当は何の作業もできません。それを解決するのがテンプレートエンジンです。テンプレートエンジンを利用すれば、PHPが出力する値を分離したHTMLテンプレートに埋め込むことが可能になります。その結果、HTMLコーディング担当者は意味のわからないPHPスクリプトを見なくて済みますし、またHTMLとPHPを分担して行うことが可能になります。

Smartyのダウンロード

Smartyはhttp://www.smarty.net/downloadで入手することが可能です。PHPのバージョンが5.2以上であればSmarty3をそうでなければSmarty2を使用します。バージョンはなるべく最新のものを選択するのがよいですが、Smarty3をダウンロードする際は「Latest Stable Release」を選択してください(「Latest Unstable Release」はベータ版みたいなものと思ってください)。また、圧縮型式も「tar.gz」と「zip」がありますが、Windows上で解凍する場合は「zip」を選択するのが無難です(アーカイバによっては「tar.gz」に対応しているものもあります)。

Smartyのインストール

ここでは、Windows環境からLinux系レンタルサーバなどにインストールすることを前提で解説していきます。まず、ダウンロードしたファイルを解凍します。解凍後、「Smarty-[VerNo]」フォルダ内に「libs」というフォルダが出来上がります。これがSmartyのテンプレートエンジン本体になります。このフォルダを「smarty」とリネームします(アップロード後でもかまいません)。「smarty」ディレクトリをFTPソフトなどで任意の場所にアップロードします(公開ディレクトリ上位あたりがベストかもしれません)。アップロードした「smarty」ディレクトリの下に「cache」「configs」「templates」「templates_c」というディレクトリを作成します。「cache」「templates_c」はキャッシュ置き場になりますのでユーザの書き込み権限が必要になります。私が利用している環境ではパーミッションが「755」でも問題なく動作していますが、場合によってはパーミッションを「777」にする必要があるかもしれません。アップロードおよびディレクトリを作成した結果、以下のような構成になっていれば問題ありません。

smarty
  ├ cache
  ├ configs
  ├ internals
  ├ plugins
  ├ templates
  ├ templates_c
  ├ Config_File.class.php
  ├ debug.tpl
  ├ Smarty.class.php
  └ Smarty_Compiler.class.php

コンフィグファイルの作成

Smartyは実行する際に、PHP側で「Smarty.class.php」を読み込んだり、Smartyが動作するのに必要なディレクトリをしてする必要があります。その都度PHPファイルに書き込むのも面倒なので、下記のようなファイルを「smarty.conf.php」という名前で作成し任意の場所に保存します。デフォルトではテンプレート側で渡された変数を表示させる際のデリミタは「{}」なのですが、エンコードがS-JISの場合に問題が発生するようなので、「<{}>」に変更しています。またサーバルートからのパスがわからない場合は、「phpinfo」関数などで調べてみてください。

スクリプト

<?php
	define('SMARTY_DIR', '/サーバルートからの絶対パス/smarty/');
	require_once(SMARTY_DIR.'Smarty.class.php');
	function & getSmartyObj(){
		static $smarty = null;
		if(is_null($smarty)){
			$smarty = new Smarty();
			$smarty->left_delimiter = '<{';
			$smarty->right_delimiter = '}>';
			$smarty->template_dir = SMARTY_DIR."templates/";
			$smarty->compile_dir = SMARTY_DIR."templates_c/";
			$smarty->config_dir = SMARTY_DIR."configs/";
			$smarty->cache_dir = SMARTY_DIR."cache/";
		}
		return $smarty;
	}
?>

Smartyを使ってみよう

ここではSmartyの使い方について解説しています。今回の解説では、PHP側のファイルは公開ディレクトリ以下の任意の位置に「smarty.test.php」として配置し、テンプレートファイルは「smarty.test.tpl」として「smarty/templates/」直下に配置します。PHPのファイルとテンプレートのファイルの文字コードは同じになるように保存してください。

スクリプト

<?php
	require_once ('smarty.conf.phpを相対パスで指定');
	$data = '今日は'.date('Y年m月j日').'です。';
	$smarty = getSmartyObj();
	$smarty->assign('data', $data);
	$smarty->display('smarty.test.tpl');
?>

テンプレート

<?xml version="1.0" encoding="EUC-JP"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-JP" />
<title>Smartyのテスト</title>
</head>
<body>
<p><{$data|escape}></p>
</body>
</html>

解説

require_once ('smarty.conf.phpを相対パスで指定')
「smarty.conf.php」を読み込みます。
$data = '今日は'.date('Y年m月j日').'です。'
今日の日付を取得したものを文字列と結合し、変数「$data」に代入しています。
$smarty = getSmartyObj()
読み込んだ「smarty.conf.php」内の関数「getSmartyObj()」を実行しその結果を変数「$smarty」に代入しています。
$smarty->assign('data', $data)
->(アロー演算子)でassignメソッドを実行し、クラス「Smarty」に変数「$data」の値を渡しています。「Smarty.class.php」を読み込んだ時点でクラス「smarty」からnew演算子によりオブジェクト「$smarty」をすでに生成しています。引数1番目はテンプレートで表示する際の変数名、引数2番目は実際にテンプレートに渡す値になります。
$smarty->display('smarty.test.tpl')
->(アロー演算子)でdisplayメソッドを実行することで、テンプレートファイル「smarty.test.tpl」が呼び出されページが表示されます。
<p><{$data|escape}></p>
テンプレート側での変数表示方法になります。PHPでassignメソッドを実行した際に1番目を引数を「data」としたのでテンプレート側での変数は「$date」となります。「<{$data}>」でも表示されるのですが「|escape」を付加することにより、「&」「"」「'」「 <」「 >」がエスケープされます。

テンプレートファイルから別のテンプレートファイルを読み込んでみよう

Smartyでは1つのページに対して、PHPファイル、テンプレートファイルがそれぞれ最低でも1つは必要となります。その都度HTMLのヘッダ部分やフッタの部分を記述していたのでは、大変非効率です。そこでここでは、「smarty.header.tpl」「smarty.footer.tpl」というファイルを作り、各テンプレートファイルから読み込んでみたいと思います。こうすることでその他の各テンプレートは短いもので済みますし、デザインの変更などは「smarty.header.tpl」「smarty.footer.tpl」とCSSファイルを書き換えることで可能となります。「smarty.header.tpl」「smarty.footer.tpl」は「smarty/templates/」直下に配置してください。

テンプレート

<{include file='smarty.header.tpl'}>
<p><{$data|escape}></p>
<{include file='smarty.footer.tpl'}>

解説

<{include file='smarty.header.tpl'}>
テンプレートファイル「smarty.header.tpl」を読み込みます。「<{include file='smarty.header.tpl' 読み込んだ先での変数名=$PHPから受け取った変数名}>」とすればPHPから受け取った値を「smarty.header.tpl」に渡すことも可能です。例えば「smarty.header.tpl」のヘッダの「title」タグ部分を「<title><{$title|escape}></title>」とします。続いて「smatry.test.tpl」の1行目を「<{include file='smarty.header.tpl' title=$title}>」と変更します。そして「smarty.test.php」で「display」メソッド実行前に「$smarty->assign('title', 'Smartyテストページ')」などとしておけば、同じテンプレートを使用していても、それぞれ違うページタイトルを設定することが可能になり、SEO対策などをすることも可能となります。

ループを使ってみよう

PHPに限らず、サーバサイドスクリプトを使っているとループによる処理が頻繁に行われます。Smartyには「foreach」によって配列を処理する機能が備わっています。今回はPEARおよびMySQLを使用してリンク集を作成しているという前提で、「foreach」の機能を解説していきたいと思います。PEARによるMySQLについての解説はデータベース接続をご覧ください。今回のデータベースついては「サイト名(カラム名:name)」「URL(カラム名:url)」という最低限の構成で解説します。

スクリプト

<?php
	$title = 'リンク集';
	require_once ('データベースのコンフィグファイルまでの相対パス/DB.conf.php');
	require_once ('コンフィグファイルまでの相対パス/smarty.conf.php');
	require_once ('DB.php');
	$db = DB::connect($dsn);
	if(PEAR::isError($db)){
  		die($db->getMessage());
	}
	$data = array();
	$result = $db->query('SELECT * FROM テーブル名');
	while($row = $result->fetchRow(DB_FETCHMODE_ASSOC)){
		$data[] = array(name=>$row['name'], url=>$row['url']);
	}
	$smarty = getSmartyObj();
	$smarty->assign('title', $title);
	$smarty->assign('data', $data);
	$smarty->display('smarty.link.tpl');
?>

テンプレート

<{include file='smarty.header.tpl' title=$title}>
<ul>
<{foreach from=$data item=value}>
<li><a href="<{$value.url}>" target="_blank"><{$value.name|escape}></a></li>
<{/foreach}>
</ul>
<{include file='smarty.footer.tpl'}>

解説

$title = 'リンク集'
テンプレートに渡すページタイトルを変数「$title」に代入しています。
require_once ('…')
コンフィグファイルおよびPEARのDBクラスを読み込んでいます。PEARはパスが通っていればファイル名だけで呼び出すことができます。「phpinfo」関数などでパスが通っているか確認してください。
$db = DB::connect($dsn)
スコープ定義演算子「::」を使用することにより、DBクラスのconnectメソッドを実行しています。成功するとオブジェクトが返されますので、変数「$db」はオブジェクトということになります。
if(PEAR::isError($db)){ … }
「PEAR::isError」メソッドで実際にデータベースへの接続が成功しているかどうか確認しています。接続に失敗している場合{ }内の処理を実行します。
die($db->getMessage())
getMessageメソッドでエラーの内容を取得しています。その内容がdie関数の引数となりますので、取得したエラーの内容を出力し、すべての処理を終了します。
$data = array()
テンプレートにデータを渡すための配列の初期化を行っています。
$result = $db->query('SQL文')
SQL文を実行し、その結果を変数「$result」に代入しています。
while($row = $result->fetchRow(DB_FETCHMODE_ASSOC)){ … }
fetchRowメソッドで取得したデータを取り出し配列「$row」に格納します。「while」によってSQL文によって抽出された行数文だけ{ … }内の処理を繰り返します。
$data[] = array(name=>$row['name'], url=>$row['url']);
取得したデータを配列「$data」に格納しています。$data[]に配列を格納していますので、多次元配列ということになります。今回はPHPで値は取り出しませんが、SQL文で抽出したデータの1行目のURLは「$data[0]['url']」で取り出すことができます。
$smarty = getSmartyObj()
読み込んだ「smarty.conf.php」内の関数「getSmartyObj()」を実行しその結果を変数「$smarty」に代入しています。
$smarty->assign('title', $title)
->(アロー演算子)でassignメソッドを実行し、クラス「Smarty」に変数「$title」の値を渡しています。
$smarty->assign('data', $data)
->(アロー演算子)でassignメソッドを実行し、クラス「Smarty」に変数「$data」の値を渡しています。変数、配列とも値の渡し方同じになります。
$smarty->display('smarty.link.tpl')
->(アロー演算子)でdisplayメソッドを実行することで、テンプレートファイル「smarty.link.tpl」が呼び出されページが表示されます。
<{foreach from=$data item=value}>
Smartyのforeach構文であり、配列に格納されている値の数だけ以下の処理を繰り返します。fromは値を取り出す配列を、itemは配列を展開する際の配列名になります。
<li><a href="<{$value.url}>" target="_blank"><{$value.name|escape}></a></li>
配列の値を取り出すには、「item」で指定した配列名+.(ドット)+キーという名前で指定します。この場合、URLは「<{$value.url}>」、サイト名は「<{$value.name|escape}>」で取り出しています。
<{/foreach}>
foreach構文の閉じタグになります。

▲ページトップに戻る