質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

バリデーション

Validationとは特定の入力データが、求められた条件に当てまっているかをチェックするために使われます。

Q&A

3回答

2297閲覧

PHPのバリデーションの最適な方法を教えて下さい

ryuuinn

総合スコア75

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

バリデーション

Validationとは特定の入力データが、求められた条件に当てまっているかをチェックするために使われます。

0グッド

2クリップ

投稿2015/10/05 13:48

質問の概要

今PHPでバリデーションする処理を書いています。
バリデーションの内容としては、コンストラクタで受け取った配列の中身をチェックするような処理です。
そこで、バリデーション処理をリファクタリングしていてふと疑問に思いました。

PHPでバリデーションを書く際の最適な方法などはあるのでしょうか。

こんな感じの処理

既存のコードでは、このように1つでもエラーになったらすぐに return false してました。
が、これだと複数のバリデーションに該当してても、どこでエラーになったかわかりづらく、テストも書きづらいという課題を感じました。

php

1class Hoge 2{ 3 private $hoge = array(); 4 private $logger = null; 5 6 public function __construct($hoge, $logger) 7 { 8 $this->hoge = $hoge; 9 $this->loger = $logger; 10 } 11 12 /** 13 * hogeのバリデーション 14 * 15 * @return boolean 16 */ 17 public function isValid() 18 { 19 if (!isset($this->hoge['id']) || !is_numeric($this->hoge['id'])) { 20 $this->logger->error('invalid_id'); 21 return false; 22 } 23 24 if (!isset($this->hoge['address']) || (strlen($this->hoge['address']) > 10)) { 25 $this->logger->error(sprintf('invalid_id id=%s', $this->hoge['id'])); 26 return false; 27 } 28 } 29} 30

こんな感じに修正してみた・・

そこで、クラスのプロパティに、 errors というものを用意して、バリデーションに引っかかったらこのプロパティに内容を追加していこうと考えました。
そうすれば、ログも全部吐かれるし、テストも、 getErrors のようなゲッターを用意して、エラーの配列が意図したものと一致してるかも確認できます。

ただ、1つ問題に遭遇しました。
これまで「この $hoge の一意なキーとなる id が存在していない」というエラー以外では、この id をログに吐く事でログチェックをやりやすくしていました。

しかし、今回からは id が存在しなくても他のバリデーションはするようにしたため、
最初のバリデーションでエラーになると、それ以降のバリデーションでエラーが起きた時にはログに吐く際の id が定義されていないため、 undefined id となってしまいます。

こういう問題ってどう解決したら良いのでしょうか。
最初の id キーの存在チェックだけ return false をしても良いかと思ったのですが、
ほかの部分との処理が異なっていてあまりすっきりしません。

php

1class Hoge 2{ 3 private $hoge = array(); 4 private $errors = array(); 5 private $logger = null; 6 7 public function __construct($hoge, $logger) 8 { 9 $this->hoge = $hoge; 10 $this->logger = $logger; 11 } 12 13 /** 14 * hogeのバリデーション 15 * 16 * @return boolean 17 */ 18 public function isValid() 19 { 20 if (!isset($this->hoge['id']) || !is_numeric($this->hoge['id'])) { 21 $this->errors[] = 'invalid_id'; 22 $this->logger->error('invalid_id'); 23 } 24 25 if (!isset($this->hoge['address']) || (strlen($this->hoge['address']) > 10)) { 26 $this->errors[] = 'invalid_address'; 27 $this->logger->error(sprintf('invalid_id id=%s', $this->hoge['id'])); 28 } 29 30 return count($this->errors) < 1; 31 } 32}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

[PHP] まとめて例外をスローする小技

以前読んだ記事を紹介します。

投稿2015/10/05 16:46

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

例外を利用するのはどうでしょうか。

また、各入力チェックをそれぞれクラス、あるいはメソッドに分けて
テストしやすいようにするとか。

投稿2015/10/05 15:22

編集2015/10/05 15:24
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こんなんでは、駄目ですかね???
'id’の存在チェックをして?なければ、ダミーを定義しておくとか?

public function isValid() { //idが$this->hogeにアルかな? if(array_key_exists('id', $this->hoge)){ if (!isset($this->hoge['id']) || !is_numeric($this->hoge['id'])) { $this->errors[] = 'invalid_id'; $this->logger->error('invalid_id'); } }else{ //idが定義されてないを一応エラーで報告 $this->errors[] = 'no_array_key_id'; $this->logger->error('no_array_key_id'); //ダミーの['id]を定義しておくとかで、以降のエラーを抑止?するとか? $this->hoge['id'] = "dummy_id"; } if (!isset($this->hoge['address']) || (strlen($this->hoge['address']) > 10)) { $this->errors[] = 'invalid_address'; $this->logger->error(sprintf('invalid_id id=%s', $this->hoge['id'])); } return count($this->errors) < 1; } }

投稿2015/11/02 20:04

ItoTomonori

総合スコア1283

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問