職業訓練生のためのPHPチュートリアル(5) valitronでバリデーションを行う

前回の記事で投稿、閲覧ができるようになりました。

職業訓練生のためのPHPチュートリアル(4) リクエストPOSTで登録
前回はHTTPリクエストメソッドがGETの場合、一覧表示をする部分を制作しました。 今回はリクエストメソッドがPOSTの場合はデータベースに登録する部分に取り掛かります。 POSTリクエスト時の処理 POSTリクエスト時の処理...

今回は投稿内容のチェック(バリデーション)とエラーの表示を作成します。

バリデーションとは?

Webアプリケーションではユーザーからの入力を受け付ける場面が多くあります。閲覧ユーザーからは「検索キーワード」、登録ユーザーからは「新規の情報登録」や「編集」などです。

入力は必ずしも正しく行われるとは限りません。人はミスを犯すものですし、悪意を持って誤った情報を登録しようとする人もいます。

  • 数字であるべきデータに文字列が含まえていないか
  • 文字数制限は守られているか
  • 電話番号、郵便番号、メールアドレスは正しい書式か

アプリケーションを作る人は「必ずしも入力は正しく行われない」と考えて、入力されたデータ、データベースに登録されるデータを検査する必要があります。

その検査をする行為をバリデーションといいます。

ユーザー求めているのはデータです。アプリケーションではありません。
アプリケーションはそのデータを整理したり探したりするための道具と言えます。
たとえばFacebookユーザーが見たいのは友人やフォローしている人の画像や文字データです。
データを見るためにスマホアプリやブラウザ(Webアプリケーション)を利用します。
データを保存するデータベースに誤った情報が入らないようにするのはとても重要なのです。

バリデーションのライブラリValitronのインストール

今回のプロジェクトにValitronをインストールします。
正規表現などでバリデーションを行う方法もありますが、Webアプリケーションを想定したバリデーションライブラリを使うことでより高度な検査を簡単に行うことが可能です。

ライブラリのインストールにはチュートリアル1でインストールしたComposerを使用します。

XamppのShellを開く

XAMPPのshell

XAMPPのコントロールパネルからShellを開きます。
今回のプロジェクトフォルダまで移動します。

# cd htdocs\examplebbs

Composerの初期設定

Composerを使用する場合、設定ファイルcomposer.jsonが必要です。
initコマンドで作成します。

# composer init
  Welcome to the Composer config generator

対話式でいくつか質問をされますが、全てエンターでスキップしても大丈夫です。

valitronのインストール

ヴァリデーション用ライブラリvalitronをインストールします。

# composer require vlucas/valitron
Using version ^1.4 for vlucas/valitron
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing vlucas/valitron (v1.4.7): Downloading (100%)
Writing lock file
Generating autoload files

index.phpにバリデーション処理を追加

フローチャートの変更

バリデーションを加えることにより、入力エラーがあると再入力が必要なためプログラムの流れに変更が発生します。

チュートリアルプログラムの流れ

入力エラーがあれば、セッション変数にエラー内容を保存してリダイレクトを行います。
また、入力値も再現する必要がありますので、入力値をMessageインスタンスに保存してフォームに戻します。

処理をコメントに記述

POST送信時の処理をコメントで記述。
実際にコードを書く前に整理してみましょう。

if($_SERVER['REQUEST_METHOD']==="POST"){
  //POSTリクエスト時の処理

  //POSTされたデータを取得
  .....前記事で実装済、省略......

  //バリデーション用の連想配列を定義

  //データのチェック(バリデーション)
  
  //データに不備が無ければ

    //データベースに登録
    try{
      //DBに登録
      .....前記事で実装済、省略......
    }catch(PDOEXception $e){
      .....前記事で実装済、省略......
    }
  
  //不備があれば

    //入力値とエラーメッセージをセッションに登録
    
  //リダイレクト
  header('Location:'.$_SERVER['SCRIPT_NAME']);
  exit();

}else{

バリデーション用の連想配列を定義:index.php

//バリデーション用の連想配列を定義
  $data = ['user_name' => $user_name, 'user_email' => $user_email, 'main' => $main];

Valitronインスタンスのコンストラクタに引数で渡す連想配列を定義しています。
$_POSTを直接渡す場合もありますが、先の処理でhtmlspecialchars関数を適用したため改めて連想配列を作り直しています。

データのチェック(バリデーション):index.php

//データのチェック(バリデーション)
  $v = new Valitron\Validator($data);
  $v->rule('required', ['user_name', 'user_email', 'main'])->message('{field}は必須です');
  $v->rule('email', 'user_email')->message('{field}が不正です');
  $v->labels(array(
    'user_name' => '名前',
    'user_email' => 'メールアドレス',
    'main' => '本文'
  ));

Valitronインスタンスに連想配列を渡した後はエラーチェックのルールをrule()メソッドを経由して指定していきます。

requiredを指定すると必須項目、emailを指定すると書式チェックを行います。
labels()メソッドを使用することで値の日本語名称を設定できます。

データに不備が無ければ: index.php

//データに不備が無ければ
  if($v->validate()) {
    //↓以下は前記事でプログラミング済
    //データベースに登録
    try{
      //DBに登録
      $pdo = new PDO(DSN, DB_USER, DB_PASS);
      $sql = 'INSERT INTO messages(user_name, user_email, main, created_at) values(:user_name, :user_email, :main, now())';
      $stmt = $pdo->prepare($sql);
      $stmt->bindValue(':user_name', $user_name, PDO::PARAM_STR);
      $stmt->bindValue(':user_email', $user_email, PDO::PARAM_STR);
      $stmt->bindValue(':main', $main, PDO::PARAM_STR);
      $stmt->execute();
    }catch(PDOEXception $e){
      print("DBに接続できませんでした。");
      die();
    }

validate()メソッドはルール設定に合致していればTrueを合致していなければFalseを返します。

データに不備があれば: index.php

} else {//不備があれば
    //入力値とエラーメッセージをセッションに登録
    $msg = new Message($user_name, $user_email, $main, '');
    $_SESSION['inputMsg'] = serialize($msg);
    $_SESSION['errorMsg'] = $v->errors();
}

ルール設定と合致しなかった場合は、エラーメッセージと復元用に作成したMessageインスタンスをセッションに登録します。インスタンスをセッションに登録する場合、serialize()関数が必要です。

データに不備がなく正しくデータベースに登録されても、不備があり再入力を求める場合もindex.phpにGETでリダイレクトします。

serialize()

データ復元の準備:index.php

}else{
  //GETリクエスト時の処理

  //エラー表示
  $user_name = '';
  $user_email = '';
  $main = '';

  if(isset($_SESSION['inputMsg'])){
    $inputMsg = unserialize($_SESSION['inputMsg']);
    $user_name = $inputMsg->get_user_name();
    $user_email =$inputMsg->get_user_email();
    $main = $inputMsg->get_main();
    //セッション変数を消去
    unset($_SESSION['inputMsg']);
  }

  //一覧表示用の配列を宣言
  $message_list = array();

GETアクセス時のコード部分に復元用のプログラムを記述します。
インスタンス変数をセッションから取り出す場合はunserialize()関数が必要です。

空の変数を用意しておき、セッション変数にデータがあれば上書きします。
データがなければ空欄のままフォームに埋め込まれますので新規登録時にもそのまま利用できます。

unserialize()

HTMLテンプレート内にエラー表示を追加:index.php

<h1 class="display-4">PHP Message Board</h1>
    <?php
        if(isset($_SESSION['errorMsg'])){
            foreach ($_SESSION['errorMsg'] as $error) {
                echo '<ul class="error">';
                foreach ($error as $value) {
                    echo "<li>".$value."</li>";
                }
                echo "</ul>";
            }
            //表示が終わったらセッション変数は消去
            unset($_SESSION['errorMsg']);
        }
    ?>
    <form method="POST">

HTMLテンプレート内に復元用のコードを追加:index.php

<form method="POST">
    <div class="form-group">
      <label for="user_name">お名前</label>
        <input type="text" class="form-control" name="user_name" id="user_name" value="<?=$user_name ?>">
        <small class="form-text text-muted">投稿者名を記入してください</small>
    </div>
    <div class="form-group">
        <label for="user_email">メールアドレス</label>
        <input type="email" class="form-control" name="user_email" id="user_email" value="<?=$user_email ?>">
        <small class="form-text text-muted">投稿者のメールアドレスを記入してください</small>
    </div>
    <div class="form-group">
        <label for="main">メッセージ</label>
        <textarea name="main" class="form-control" id="main" rows="3"><?=$main ?></textarea>
        <small class="form-text text-muted">メッセージ本文</small>
     </div>
     <button type="submit" class="btn btn-primary">投稿</button>
 </form>

少し長くなりましたが、バリデーション機能とデータの復元機能を追加しました。
動作確認してエラーが表示されるかどうかチェックしてみてください。
表示されればプログラムとしては一応完成です。お疲れ様でした。

かなり長くなりましたので、どこがどの部分かわかりにくいかもしれません。
ここまでの内容はGithubにcomplete.phpとして置いていますので比較してみてください。

タイトルとURLをコピーしました