phpのような「動的型付け言語」はデータ型の検査が適当になりがち。また、phpはgetやpostで渡された値をそのまま変数として扱えたりするので、便利な反面罠も多い。多くはfatalエラーまではいかないが、できる限りwarningやnoticeエラーを出さないよう丁寧なプログラミングを心がけたい。
phpの特徴も踏まえつ「入力値に対する条件分岐」処理作成時には以下のような値がくることを想定してバリデーションすること。
- 文字列・数値
- NULL値
- 真偽値・配列・オブジェクト
- 空入力
- 未定義な値
- 型違いの値
- 想定外のGET値
- 悪質なスクリプト
- 入力ミス(メアド・URL)
- スキーム違い(http/https/mailto)
==は型の相互変換を自動で行ってしまう、null と "" が同等となる。下のコードでは文字列の数値変換が起きて true が返る
$bar = "3aaa";
$foo = 3;
if($bar == $foo){
return true;
}else{
return false;
}
htmlspecialcharacters()
によるエスケープを出力時に行う。タグだけ取り除くstrip_tagsっていうのも。
function h($str) {
return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
}
isset()
は未定義 or nullでないかどうかをエラーを出さずに検査する優秀な構文。nullもtrueを返す。
下のコードでは、入力されていないのか、正しく送信されていない(フォームのaction先に直接飛んだ)のか判別できる。
if (!isset($_POST['email'])) {
$errors[] = 'アドレスが送信されていません';
} elseif ($_POST['email'] === '') {
$errors[] = 'アドレスが入力されていません';
}
empty()
は未定義か、型変換してfalseと同等かどうかを検査する構文。型変換する挙動で 0 や "0" も false になるので利用には注意。DB問い合わせしたのち「未定義か、中身がない」状態を切り分けたいときに !empty()
とかで使ったりもする。
WEBの場合、外部からの入力は「文字列」「配列」の二種類。これについて型検査ができる。
// 文字列検査
if (!isset($_POST['email'])) {
$errors[] = 'アドレスが送信されていません';
} elseif (!is_string($_POST['email'])) {
$errors[] = 'アドレスが不正送信されました';
} elseif ($_POST['email'] === '') {
$errors[] = 'アドレスが入力されていません';
}
// 配列検査
if (!isset($_POST['params']) || !is_array($_POST['params'])) {
$errors[] = 'パラメータが送信されていません';
} else {
foreach ($params as $key => $value) {
if (!is_string($value)) {
$errors[] = "パラメータ{$key}が不正です";
}
}
}
GETやPOSTで受け取る値のインデックスに対して「適切なクエリ・値かどうか」をフィルタリングできる新しめのやつ。キャスト(型指定)での抽出もできる。適切でないときは false が、インデックスが未定義のときはnullが返る。
// 受け取るGETクエリ [ ?a=foo&b[]=bar ]
$a = filter_input(INPUT_GET, 'a'); // "foo"
$b = filter_input(INPUT_GET, 'b'); // false
$c = filter_input(INPUT_GET, 'c'); // null
// キャスト(型指定)あり
$a = (string)filter_input(INPUT_GET, 'a'); // "foo"
$b = (string)filter_input(INPUT_GET, 'b'); // ""
$c = (string)filter_input(INPUT_GET, 'c'); // ""
// POSTの未定義や想定外の型の検出
$email = (string)filter_input(INPUT_POST, 'email');
値の中身について有効な形式かどうかを自作の独自フィルタリングにかけられる関数。使い方はリファレンス参照して。
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo "正しいEメールアドレスです";
} else {
echo "Eメールアドレスの形式が不正です";
}
$_POST,$_GETを受け取る処理 : http://qiita.com/mpyw/items/2f9955db1c02eeef43ea
PHPでよくあるバリデーション : http://qiita.com/mpyw/items/346f1789ad0e1b969ebc