モデルのデータの検証
フレームワークを使えないレンタルサーバーで、生の$_POST
を検証する場合。
$_POST
はユーザーからの投稿データであり信用できないものである。
そのため検証やサニタイズが必要になる。
intデータのバリデーション
int
のデータはコメントで教えてもらったfilter_var
で検証できそう。
$valid = filter_var($_POST['age'], FILTER_VALIDATE_INT);
if ($valid === false) {
die("invalid age");
}
この関数はパースに失敗するとfalse
を返す。
$_POST['age']
が整数でない場合はパースに失敗し、$valid
がfalse
になる。
floatデータのバリデーション
floatの場合はFILTER_VALIDATE_FLOAT
を使う。
モデル
データモデルのクラスを作る。
フレームワークは使えないので自前で作る。
class PersonModel {
function __construct() {
$this->age = null;
$this->weight = null;
}
function clean() {
$this->age = filter_var($this->age, FILTER_VALIDATE_INT);
$this->weight = filter_var($this->weight, FILTER_VALIDATE_FLOAT);
}
function validate() {
$this->clean();
if ($this->age === false || $this->age < 0 || $this->age >= 200) {
throw new \Exception('invalid age value');
}
if ($this->weight === false || $this->weight < 0 || $this->weight >= 500) {
throw new \Exception('invalid weight value');
}
}
}
こんなクラスを作ったらPOSTデータを突っ込んでクリーニングと検証を行う。
$person = new PersonModel();
$person->age = $_POST['age'];
$person->weight = $_POST['weight'];
try {
$person->validate();
} catch (\Exception $e) {
die($e->getMessage());
}
try {
$person->save();
} catch (\Exception $e) {
die($e->getMessage());
}
クリーニングとバリデーションは分けてやるべきなのか?
このPersonModel
ではデータのクリーニングと検証を分けて行っている。
validate()
内ではclean()
を呼び出しているので、検証の時はデータのクリーニングを必ずやるようになる。
filter_var()
の性質上、値をフィルタしてその返り値で検証するというものなので、検証とクリーニングを切り離すのは2度手間になりそう。
またクリーニングではメンバ変数に直接クリーンした値を入れているが、これは別のcleaned_data
などを作ってそこに入れた方が、元のデータを損失しないで済む。これはDjangoなどの設計ではそうなっている。
しかしこういうのを突き詰めていくと・・・
しかしこういうことを考えると、今度はIntField
クラスとかFloatField
クラスとかが欲しくなる。
そうなるとフレームワーク作り始めてしまうのだが、こわいので手は出さず・・・。
うーん、プログラミングは時間泥棒、はまるとどこまでも吸い取られる!
おわりに
今まで整数の検証はintval
でやっていたが、filter_var
なるものを教えてもらったのでよかった。
おわり。