if 文, switch 文を使わない条件分岐

入門書にはレベルが高く、解説している本はないが、知っていて絶対損はしないテクニック。


このテクニックの代表例はPHPプログラマーの間で知らない人はいないであろう PEAR::DB 。( factory メソッドで使用されています。)


では、さっそく。


【お題】

運命をリクエスト変数として受け取り、運命に応じ、何らか処理をするアプリケーション

<?php
/**
 * ありがちなパターン( switch 文も同様 )
 * => ソースを丁寧に読んでも何の意味もありません、ざっと流し読みして下さい。
 */

$omikuji = $_REQUEST['omikuji'];

if ($omikuji == 'daikichi') {
	include('includes/daikichi_class.php');
	$object = new daikichi_class();
	// -- 運勢に応じた処理(処理) -- //
} elseif ($omikuji == 'kichi') {
	include('includes/kichi_class.php');
	$object = new kichi_class();
	// -- 運勢に応じた処理(処理) -- //
} elseif ($omikuji == 'chukichi') {
	include('includes/chukichi_class.php');
	$object = new chukichi_class();
	// -- 運勢に応じた処理(処理) -- //
} elseif ($omikuji == 'syouchukichi') {
	include('includes/syouchukichi_class.php');
	$object = new syouchukichi_class();
	// -- 運勢に応じた処理(処理) -- //
} elseif ($omikuji == 'kyou'){
	include('includes/kyou_class.php');
	$object = new kyou_class();
	// -- 運勢に応じた処理(処理) -- //
} elseif ($omikuji == 'daikyou') {
	include('includes/daikyou_class.php');
	$object = new daikyou_class();
	// -- 運勢に応じた処理(処理) -- //
} else {
	die('運勢に対応するクラスがありません。人としての道を踏み外してませんか?');
}
?>


これを if 文, switch 文を使わない条件分岐テクニックを使うと以下。

<?php
/**
 * スッキリパターン
 */
$omikuji   = $_REQUEST['omikuji'];
$classname = $omikuji.'_class';
@include('includes/' . $classname . '.php');
if (!class_exists($classname)) {
	die('運勢に対応するクラスがありません。人としての道を踏み外してませんか?');
}
$object = new $classname();
// -- 運勢に応じた処理(処理) -- //
?>

条件分岐する回数が多いときは、美しくて、効率もよく、一石二鳥。



[ 追記 ]

リクエスト変数をもとにファイルを include(require)することは、実装方法によっては重大な脆弱性につながるので、一般ユーザー向けに公開する場合には注意が必要です。(関連用語:パストラバーサル, ディレクトリトラバーサル