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

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

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

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

バリデーション

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

Q&A

解決済

3回答

3151閲覧

PHPでバリデーションを共通化してまとめたい

dog57

総合スコア131

PHP

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

バリデーション

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

0グッド

3クリップ

投稿2018/03/09 01:57

編集2018/03/11 01:11

PHPでバリデーションを共通化してまとめたいです。
具体的には下記のコードを

php

1// 名前の未入力チェック 2 if (empty($name)) { 3 $errors[] = "名前を入力してください。"; 4 } 5 6 // メールアドレスの未入力チェック 7 if (empty($email)) { 8 $errors[] = "メールアドレスを入力してください。"; 9 } 10 11 // パスワードの未入力チェック 12 if (empty($password)) { 13 $errors[] = "パスワードを入力してください。"; 14 } 15 16 // 電話番号の未入力チェック 17 if (empty($tel)) { 18 $errors[] = "電話番号を入力してください。"; 19 } 20 21 // 都道府県の未入力チェック 22 if ($prefectures == "選択") { 23 $errors[] = "都道府県を選択してください。"; 24 } 25 26 // 27 // 文字数チェック 28 // 29 30 // 名前の文字数チェック 31 if (strlen($name) >= 60) { 32 $errors[] = "氏名が長すぎます。"; 33 } 34 35 // パスワード文字数チェック(8文字以上か) 36 if (preg_match("/^[a-zA-Z1-9]{1,7}$/", $password)) { 37 $errors[] = "パスワードは8文字以上で入力してください。"; 38 } 39 40 // 電話番号の文字数チェック(10文字 or 11文字) 41 if (strlen($tel) >= 1 && strlen($tel) <= 9 && preg_match("/^[0-9]+$/", $tel)) { 42 $errors[] = "電話番号は10文字か11文字で入力してください。"; 43 } elseif (strlen($tel) >= 12 && preg_match("/^[0-9]+$/", $tel)) { 44 $errors[] = "電話番号は10文字か11文字で入力してください。"; 45 } 46 47 // 48 // 形式チェック 49 // 50 51 // メールアドレス形式チェック 52 if (!preg_match("/^([a-zA-Z0-9])+([a-zA-Z0-9._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9._-]+)+$/", $email) && $email !== "") { 53 $errors[] = "メールアドレスに間違いがあります。"; 54 } 55 56 // 電話番号の形式チェック 57 if (preg_match("/[-]+/", $tel)) { 58 $errors[] = "電話番号はハイフンなしで入力してください。"; 59 } 60 61 // 電話番号の半角チェック 62 if (preg_match("/[a-zA-Z]/", $tel) && $tel !== "") { 63 $errors[] = "電話番号は半角数字で入力してください。"; 64 } 65 66 67 68 if (count($errors) >= 1) { 69 $_SESSION['errors'] = $errors; 70 71 header("location: registration_form.php"); 72 exit; 73 74 } else { 75 76 $errors = array(); 77 78 }

下記のようにまとめてみました。
まとめたやつは

php

1require_once('./validation.php'); 2name_validation();

みたいに使っていこうと思っています。
ですが、1個1個メソッドを作るのがとてもめんどうなのですが、
1つ1つメソッドを作る以外に、もっとまとめられる方法はありますか?

validation.php

php

1<?php 2require_once('../config/config.php'); 3 4 5 function name_validation() { 6 7 // 名前の未入力チェック 8 if (empty($_SESSION['name'])) { 9 $errors[] = "名前を入力してください。"; 10 } 11 12 } 13 14 function email_validation() { 15 16 // メールアドレスの未入力チェック 17 if (empty($_SESSION['email'])) { 18 $errors[] = "メールアドレスを入力してください。"; 19 } 20 21 } 22 23 function password_validation() { 24 25 // パスワードの未入力チェック 26 if (empty($_SESSION['password'])) { 27 $errors[] = "パスワードを入力してください。"; 28 } 29 30 } 31 32 function tel_validation() { 33 34 // 電話番号の未入力チェック 35 if (empty($_SESSION['tel'])) { 36 $errors[] = "電話番号を入力してください。"; 37 } 38 39 } 40 41 function prefectures_validation() { 42 43 // 都道府県の未入力チェック 44 if ($_SESSION["prefectures"] == "選択") { 45 $errors[] = "都道府県を選択してください。"; 46 } 47 48 } 49 50 51 52 // 53 // 文字数チェック 54 // 55 56 function name_length_validation() { 57 58 // 名前の文字数チェック 59 if (strlen($_SESSION['name']) >= 60) { 60 $errors[] = "氏名が長すぎます。"; 61 } 62 63 } 64 65 function password_length_validation() { 66 67 // パスワード文字数チェック(8文字以上か) 68 if (preg_match("/^[a-zA-Z1-9]{1,7}$/", $_SESSION['password'])) { 69 $errors[] = "パスワードは8文字以上で入力してください。"; 70 } 71 72 } 73 74 function tel_length_validation() { 75 76 // 電話番号の文字数チェック(10文字 or 11文字) 77 if (strlen($_SESSION['tel']) >= 1 && strlen($_SESSION['tel']) <= 9 && preg_match("/^[0-9]+$/", $_SESSION['tel'])) { 78 $errors[] = "電話番号は10文字か11文字で入力してください。"; 79 } elseif (strlen($_SESSION['tel']) >= 12 && preg_match("/^[0-9]+$/", $_SESSION['tel'])) { 80 $errors[] = "電話番号は10文字か11文字で入力してください。"; 81 } 82 83 } 84 85 86 // 87 // 形式チェック 88 // 89 90 function email_format_validation() { 91 92 // メールアドレス形式チェック 93 if (!preg_match("/^([a-zA-Z0-9])+([a-zA-Z0-9._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9._-]+)+$/", $_SESSION['email']) && $_SESSION['email'] !== "") { 94 $errors[] = "メールアドレスに間違いがあります。"; 95 } 96 97 } 98 99 function tel_format_validation() { 100 101 // 電話番号の形式チェック 102 if (preg_match("/[-]+/", $_SESSION['tel'])) { 103 $errors[] = "電話番号はハイフンなしで入力してください。"; 104 } 105 106 } 107 108 function te_halfSize_validation() { 109 110 // 電話番号の半角チェック 111 if (preg_match("/[a-zA-Z]/", $_SESSION['tel']) && $_SESSION['tel'] !== "") { 112 $errors[] = "電話番号は半角数字で入力してください。"; 113 } 114 115 } 116 117

イメージ説明

validation.php

<?php require_once('../config/config.php'); // バリデーションクラス class Validation { // コンストラクタ(construct) function check_Validation($input_control = [], $input_data = []) { $result = []; //チェック結果配列 foreach ($input_control as $control_name => $info) { // 入力情報が存在するか if (array_key_exists($control_name, $input_data)) { $value = $input_data[$control_name]; $rules = explode("|", $info["rule"]); // バリデーションルールの引き出し foreach ($rules as $r) { // 指定されたルールをループ $rule = explode("-", $r); // ルール設定の切り出し $rule_name = $rule[0]; // ルール名 $rule_setting = $rule[1]; // ルール設定 switch ($rule_name) { // 入力が空の場合 case "empty": if ($this->empty_check($value)) { $result[$control_name][] = $info["name"].'を入力してください。'; } break; // 最大文字数のチェック case "max": if ($this->max_check($value, $rule_setting)) { $result[$control_name][] = $info["name"].'は'.$rule_setting.'文字以内で入力してください。'; } break; } } } } return $result; } // 空のチェック public function empty_check($value = "") { return empty($value); } // 入力文字数のチェック public function max_check($value = "", $max = 60) { return mb_strlen($value) > $max; } }

registration_confirm.php 一部抜粋

// POST時 if (filter_input(INPUT_SERVER, 'REQUEST_METHOD') == 'POST') { $_SESSION["name"] = filter_input(INPUT_POST, 'name'); $_SESSION["email"] = filter_input(INPUT_POST, 'email'); $_SESSION["password"] = filter_input(INPUT_POST, 'password'); $_SESSION["tel"] = filter_input(INPUT_POST, 'tel'); $_SESSION["prefectures"] = filter_input(INPUT_POST, 'prefectures'); $_SESSION["hobby"] = filter_input(INPUT_POST, 'hobby', FILTER_DEFAULT,FILTER_REQUIRE_ARRAY); $_SESSION["gender"] = filter_input(INPUT_POST, 'gender'); $_SESSION["contact"] = filter_input(INPUT_POST, 'contact'); $name = $_SESSION["name"]; $email = $_SESSION["email"]; $password = $_SESSION["password"]; $tel = $_SESSION["tel"]; $prefectures = $_SESSION["prefectures"]; $hobby = $_SESSION["hobby"]; $gender = $_SESSION["gender"]; $contact = $_SESSION["contact"]; // 対象コントロール→バリデーションルール $input_control = [ "name" => [ "name" => "氏名", "rule" => "empty|max-60" ], "tel" => [ "name" => "電話番号", "rule" => "empty|min-10|-|halfSize" ], "password" => [ "name" => "パスワード", "rule" => "empty|min-8" ], //・・・・以下、対象の入力項目とルールを定義 ]; $result = new Validation($input_control, $_SESSION); if (count($result) > 0) { $_SESSION['result'] = $result; header("location: registration_form.php"); } else { $result = array(); } } // // Twig // // Composerで作成されたautoload.phpを読み込む require_once ('../vendor/autoload.php'); // Twig_Loader_Filesystem と Twig instance の生成を読み込む require_once('../config/twig.php'); // render echo $twig->render('registration_confirm.html', array ( 'name' => $name, 'email' => $email, 'password' => $password, 'tel' => $tel, 'prefectures' => $prefectures, 'hobby' => $hobby, 'gender' => $gender, 'contact' => $contact, 'result' => $result, 'string' => $string, ) );

・registaration_form.php (登録フォーム) 一部抜粋

上の確認フォームからエラーメッセージをリダイレクトで受け取っています。

順番は registration_form.php → registration_confirm.php
registration_confirm.php でエラーがあれば registration_form.php にリダイレクト

// エラーメッセージ if (isset($_SESSION['result'])) { if (count(array($_SESSION['result'])) >= 1) { $result = $_SESSION['result']; } }

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

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

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

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

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

guest

回答3

0

ベストアンサー

私なら、どっかのフレームワークからコード持ってきます。
大抵のフレームワークなら、このあたりの実装はしっかりねられているので。

特殊なチェックはコールバック関数で渡す感じの実装しとけば、大体対応できると思います。

余談
「共通化してまとめたい」って質問ですが、「もう少し見通しを良くする」って方向でコード書くと、自然と共通化されます。読みやすいコードを書くように意識すると良いですよ。

投稿2018/03/09 02:57

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

個別にしすぎているので汎用性が低く、今の状態でも「まとめた」とは言えません。
空のバリデーションは1つにできますし、最大文字数もまとめられます。
電話番号チェックなどはわけるのではなく1つにできそうです。

それぞれのコントロールに対してバリデーションルールをつけてそのルールに基づいてチェックしてはどうでしょうか。
あとはルールを追加していけばいいだけなので、入力項目個別に作るよりは様々な用途に使えて、メソッド追加も最小限に済むと思います。

というわけで、私ならクラス化します。

※ざっと作ったので動作検証ほとんどできてませんが・・・。

バリデーション呼び出し側

php

1require_once('./validation.php'); 2 3//対象コントロール→バリデーションルール 4$input_control=[ 5 "name"=>[ 6 "name"=>"氏名", 7 "rule"=>"empty|max-50" 8 ], 9 "empty"=>[ 10 "name"=>"電話番号", 11 "rule"=>"empty|tel" 12 ], 13 "password"=>[ 14 "name"=>"パスワード", 15 "rule"=>"password" 16 ], 17 18・・・・以下、対象の入力項目とルールを定義 19]; 20 21$result = new Validation($input_control,$_SESSION); 22 23if(count($result) > 0){ 24 //エラーがある場合の処理 25 26}else{ 27 //エラーがない場合の処理 28} 29

バリデーション(validation.php)

php

1 2//バリデーションクラス 3class Validation{ 4 //コンストラクタ 5 function Validation($input_control = [],$input_data = []){ 6 $result = [];//チェック結果配列 7 foreach($input_control as $control_name=>$info){ 8 //入力情報が存在するか 9 if(array_key_exists($control_name,$input_data)){ 10 $value = $input_data[$control_name]; 11 $rules = explode("|",$info["rule"]);//バリデーションルールの引き出し 12 foreach($rules as $r){ //指定されたルールをループ 13 $rule = explode("-",$r); //ルール設定の切り出し 14 $rule_name = $rule[0]; //ルール名 15 $rule_setting = $rule[1]; //ルール設定 16 switch($rule_name){ 17 //入力空の場合 18 case "empty": 19 if($this->empty_check($value)){ 20 $result[$control_name][] = $info["name"].'を入力してください。'; 21 } 22 break; 23 //最大文字数のチェック 24 case "max": 25 if($this->max_check($value,$rule_setting){ 26 $result[$control_name][] = $info["name"].'は'.$rule_setting.'文字以内で入力してください。'; 27 } 28 break; 29 30           ・・・・以下、バリデーションルールを追加 31 } 32 33 } 34 } 35 } 36 37 return $result; 38 } 39 40 //空のチェック 41 private function empty_check($value = ""){ 42 return empty($value); 43 } 44 //入力文字数のチェック 45 private function max_check($value = "",$max = 50){ 46 return mb_strlen($value) > $max; 47 } 48 49 ・・・以下、バリデーションチェック処理を追加 50} 51

パスワードとかは入力必須ではないということはないと思いますので、そういう場合は「パスワードチェック」に空かどうかも含ませるというのもありです。

エラーメッセージなども設定で持ってそこから取得するようにすればswitchすらも不要にできる可能性があります(そこは発想とやり方次第ですね)
いずれにしてもバリデーションルールが増えればメソッドも増えます。

追記:
filter_var()という関数があるのでこちらを使うとメールアドレスのチェックなどはかなり楽です(自身のチェックしたい内容全て網羅しているとは限りませんが・・・)

投稿2018/03/09 02:26

編集2018/03/09 02:48
m.ts10806

総合スコア80850

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

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

退会済みユーザー

退会済みユーザー

2018/03/09 03:41

ちなみに teratail のパスワードは必須ではない (SNS認証登録時)
m.ts10806

2018/03/09 03:50 編集

なるほど。そこは用途によりですね。複合チェックもあるので、そこはパターン増やすということで。
dog57

2018/03/09 04:44

ありがとうございます! ちなみにですが、 empty_check はPHPのデフォルトの関数でしょうか?
m.ts10806

2018/03/09 05:01 編集

いいえ。PHPマニュアルを検索してみると分かりますが、ありません。 自身でチェック用の関数を作っています。 Validationクラス内にありますよね。empty_check()
dog57

2018/03/09 09:23

ありがとうございます! 実際に、上記の方法で検証してみたのですが 質問欄の一番下に貼ったバグが発生してしまいました。 自力では解決できなかったのですが どんな解決方法が適していますでしょうか?
m.ts10806

2018/03/09 11:02

ソースコードをご提示ください。エラーメッセージだけではわかりません。
m.ts10806

2018/03/09 11:27 編集

エラーメッセージそのまま調べてもらえればわかりますが、オブジェクト(今回はValidation)の扱いがどこかで間違っているのではと思いますが。何かでint型にしようとしているような記述があるのではないでしょうか。
dog57

2018/03/11 00:52

質問欄の画像の下にコードを追記いたしました。
guest

0

汎用性を前提に場合分けをしてelseifでつないでいけばよいでしょう

PHP

1<?PHP 2$list=[ 3 "name"=>[ 4 "kanji"=>"名前", 5 "required"=>true, 6 "max_length"=>3, 7 ], 8 "email"=>[ 9 "kanji"=>"メールアドレス", 10 "required"=>true, 11 "min_length"=>5, 12 ], 13 "password"=>[ 14 "kanji"=>"パスワード", 15 "required"=>true, 16 "min_length"=>8, 17 "max_length"=>10, 18 ], 19 "tel"=>[ 20 "kanji"=>"電話", 21 "required"=>true, 22 "pattern"=>"/^[0-9]+$/", 23 ], 24 ]; 25$errors=[]; 26array_walk($list,function($x,$y) use(&$errors){ 27 $v=filter_input(INPUT_GET,$y); 28 if(is_null($v)){ 29 return false; 30 }elseif(empty($v) and isset($x["required"]) and $x["required"]){ 31 $errors[]=$x["kanji"]."は必須"; 32 }elseif(isset($x["min_length"]) and isset($x["max_length"])){ 33 $errors[]=$x["kanji"]."の長さは".$x["min_length"]."文字以上".$x["max_length"]."文字以下"; 34 }elseif(isset($x["min_length"]) and $x["min_length"]> mb_strlen($v)){ 35 $errors[]=$x["kanji"]."の長さは".$x["min_length"]."文字以上"; 36 }elseif(isset($x["max_length"]) and $x["max_length"]< mb_strlen($v)){ 37 $errors[]=$x["kanji"]."の長さは".$x["max_length"]."文字以下"; 38 }elseif(isset($x["pattern"]) and !preg_match($x["pattern"],$v)){ 39 $errors[]=$x["kanji"]."は使用できない文字が含まれている"; 40 } 41}); 42if(count($errors)>0) print_r($errors); 43?> 44<form> 45<input type="text" name="name" placeholder="名前"><br> 46<input type="text" name="email" placeholder="メールアドレス"><br> 47<input type="text" name="password" placeholder="パスワード"><br> 48<input type="text" name="tel" placeholder="電話"><br> 49<input type="submit" value="go"> 50</form>

投稿2018/03/09 02:51

yambejp

総合スコア114829

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問