バリデーションとは受け付けない値を弾いて、確かな(valid)値だけを扱うという処理です。 こう説明されてもわかりにくいと思うので、いつもの生活の中でどのようなチェックが行われているかを例に説明しましょう。 アンケートフォームなどで数字の項目に文字を入れるとエラーになったり、携帯電話で着信拒否の番号を登録したり、身近で値のチェックを行っていますね。 本書で作成したレシピアプリでも、POSTやGETで値を取得していますが、このような値はHTML5やJavaScriptなどで入力チェックを行っていても信用してはいけません。ここで重要になるのがバリデーションです。
※Mac環境の場合は、以下本文に登場するプログラム内の「¥」(半角エンマーク)を「\」(半角バックスラッシュ)に入力しなおす必要があります。日本語キーボードの場合、半角バックスラッシュは[option]+[¥]キーを押すことで入力できます。
これらを調べて、必要の無いものを除外する必要があります。
バリデーションに適した関数を紹介しましょう。 preg_matchという関数です。 preg_match()は正規表現により、値が期待するパターンにマッチするかを検査します。
図
正規表現というと難しいですが、ここでは下記のサンプルを見て雰囲気をつかんでください。
preg_match('/¥A[123]¥z/',変数);
preg_match('/¥A[0-9]{1,4}+¥z/',変数);
preg_match('/¥A[[:^cntrl:]]{1,100}+¥z/u',変数);
preg_match('/¥A[ r n[:^cntrl:]]{1,150}+¥z/u',変数);
なんとなく予想がつきませんか? パターンの部分で/¥A ... ¥z/に挟まれた中にそれぞれ違いがあります。 ここでは細かく説明しませんが、この書き方を覚えておいてください。
| 項目 | 内容 |
|---|---|
| // | //囲まれた部分に正規表現が入っている |
| ¥A | 文字列の先頭 |
| ¥z | 文字列の最後 |
| [] | []の中が使って良い文字列になる |
| 0-9 | 0〜9の数字 |
| a-z | アルファベット |
| [:^cntrl:] | 制御文字以外 |
| r n | 改行 |
| + | 一文字以上の繰り返し |
| {} | {}の直前のパターンの有効桁(文字)数 |
| u | UTF-8が対象 |
*上記の表は例に使われている正規表現の簡単な説明です。
さらに詳細な内容ついては「PHP 正規表現」などで検索し、どのようなものなのか勉強してください
(コピペでの利用は意図しない処理になる場合もあるので、よく内容を理解して利用しましょう)。
この先では上記サンプルのみを用います。
さてバリデーションをするためには、色々な条件で受け付けない条件を設定する必要があります。 そのようなときにif文を用いて複数の条件を1回で判定する方法をここで補足します。 まずif文の構文を見てみましょう。
でしたね。この条件というところがポイントで、中が真(TRUE),偽(FALSE)かで条件の判定を行います。 elseも覚えましたが、ここでは条件の部分に注目して新しい使い方を覚えましょう。
●●では無いというような条件を利用したい場合は多いと思います。そのような場合は論理演算子の!を利用することで条件の否定を行うことができます。
例:emptyでは無い場合
例を見てみると何か気づくと思いますが、 if文の条件で!(否定)を付けることはelseの条件のときと同じです。 真(true)の側の判定が不要な場合、!を用いるとif文が短くなり可読性がよくなるので覚えておきましょう。
例1をif〜elseで表すと
条件文でよく出てくるので覚えておくといいでしょう。
いままではシンプルな判定を行ってきましたが複合的な判定も必要になります。 例えば●●かつ●●、や●●または●●といった判定です。
かつの場合は論理積と呼ばれるもので、2つの条件を&&でつなぎます。 またはの場合は論理和と呼ばれ、2つの条件を||でつなぎます。 なお、複数の条件を利用する場合、1つ1つの条件を()で括ることで可読性が増します。
例:
下記でも利用するので覚えておいてください。
emptyとは、逆に存在するということを判定するissetという言語構造があります。 先ほど!(否定)を学びました。この2つは完璧に対になるものではないので注意が必要です。 大きな違いは0の判定を行ったときに0を空とするのか、数値が入力されているのかどちらで判定するかです。
このような短いサンプルをtest.phpなどとして実行してみましょう。 結果は int(0) bool(true) bool(false) このように返ってくるので注意が必要です。
※他にも$a="";なども違う判定が返ります。
レシピアプリではidはautoincrementで1から始まりました。通し番号では0から始まる場合もありますね。このような場合、上記のようにif (empty($id)) と行うと0も条件を満たしたと判断されてしまいます。これはempty()が0を真(TRUE)と判定するためです。このような場合は値がある場合はisset()という構文を用いましょう。isset()は0が入力されても入力があると判定します。このisset()に先ほど説明に出てきた!(否定)を行うと何も入力されていない場合の判定が行えます。なお、0や未入力の扱いには注意が必要です。マニュアルを参考にテストを行い意図したデータを判定しているか確認しましょう。
PHPマニュアルなどを参考にして、仕様上どちらが最適かを検討してください。
http://php.net/manual/ja/function.isset.php
http://php.net/manual/ja/function.empty.php
いよいよ実際にバリデーションを行っていきましょう。 まずはIDの場合を考えてみます。
idのみ(detail.php、edit.php、delete.php)
いまIDの値はどのように作成されるかというと、 データベースを作成したときのauto incrementが有効になっているので、 1から順にカウントアップしていきます。 PHPにもMySQLにも扱える型により扱える限界はあります。 ※執筆時点でのMAMPおよびXAMMPの環境では、MySQLのINT型の範囲-2147483648〜2147483647、PHPのinteger型の最大値9223372036854775807(脚注) いままで決めていませんでしたが、今回のプログラムでは1000件まで入力できることに決めましょう。 とすると、IDに入力されるべき整数は1-1000の整数ということになります。 では、それ以外の値についても下記表のように、入力できる値に制約を設けましょう。
表:許可する変数
| 項目 | 内容 |
|---|---|
| ID | 1から1000までの整数 |
| 料理名 | 100文字までの文字列 |
| カテゴリ、難易度 | 1〜3の整数 |
| 予算 | 0-9999までの整数 |
| 作り方 | 150文字の文字列 |
ではそれぞれの項目についてソースコードを修正していきましょう。 レシピの数は1000個まで登録できるようにしましょう。
対象となるファイルはdetail.php、edit.php、delete.phpになります。 それぞれの箇所から該当する箇所を探して修正しましょう。
元の箇所
変更後
さてURLにIDが付与されてくるのは、いま修正した3つのファイルでしたが、 もう一箇所IDを受け渡す処理がありましたね。 更新作業の送信をした後にデータベースに書き込むupdate.phpです。 update.phpは次に入力フォームの値のチェックで修正もしますが、 同様の処理を先に入れておきましょう。 該当する行を見てみると違いはGETとPOSTだけですね。同様に修正しておきましょう。
では修正のテストしてみましょう。
どうでしょう。追加、更新に問題は無かったですか?メッセージは正しく表示されましたか? 処理が上手くいかない場合はもう一度見直しましょう。 エラーメッセージの内容をよく読んで、どこか原因か探りましょう。
detail.php、edit.php、delete.php共に修正して、index.phpから処理が正しく動くことを確認してください。
次は新規追加と更新の修正を行います。 つまりadd.phpとupdate.phpを修正します。
この処理はadd.phpとupdate.phpで共通する部分が多いので、 先ほど覚えたinclude_onceを利用しましょう。 db_config.phpと同じ階層にerror_check.phpを作成しましょう。
いままではif文の後{}で括らずにすぐにthrow new Exceptionを記述していましたが、 判定やメッセージなど1行で表示するには長くなってきたので、 if{}の書き方にしましょう(いままでは誌面の節約に一行の記述が多かったのですが、{}を使いましょう)。
それぞれのpreg_matchによる判定で利用している正規化表現はこのレッスンの冒頭で説明したものばかりです。内容を見比べてください。 POSTされたそれぞれの変数と比べてマッチしないもの(!を先頭に付ける)でExceptionを発生させます。 Exceptionの引数のエラーメッセージもエラーの内容がわかるものにしましょう。
後は実際にadd.phpに、このファイルを読み込むだけです。db_config.phpの読み込み箇所を参考に追加してみましょう。
追加する箇所はtryのすぐ後で項目ごとに変数に格納する前です。
※includeできない場合はファイル名で検索して、保存場所を指定してください。
これでadd.phpは完了です。 includeさせると、そのファイルの中身がプログラムに取り込まれます。 これでadd.phpが実行されるたびに毎回、いま作成したバリデーション処理が実行されることになります。
では実際に予算に9999より大きな数字を入れてみてメッセージを確認してみましょう。 エラーメッセージが表示されましたか? これでバリデーションは完成です。 お疲れ様でした!
バリデーションは実際にWebアプリを公開する上で必要になってきます。 ぜひこの仕組を覚えておいて活用してください。