おべんきょうメモ

Web制作の勉強メモ ほぼほぼ自分用

PHPメモ バリデーションチェック編

ユーザーに何らかのデータを入力させるタイプのWebサイトを作る場合、そのデータがこっちの想定した形式できちんと入力されているかをチェックした上でデータを通さないとDBにエラーを吐かれて想定外の動作をしたりするかもしれない
のでDBにデータを通す前に形式チェックをする 通称バリデーションチェック

大まかなバリデーションチェックの種類

共通

未入力

empty$str===''辺りかな
empty0も空と判定するので数値を扱う場合は空文字と比較してやる方がいいかもね

文字数

mb_strlen($str)は文字列の文字数をカウントする関数、これと数値を比較してやる

<?php
mb_strlen('オムライス専門店'); // 結果:8

// 文字列が30文字以内かどうかを比べたい場合
$str = '期間限定バナナチョコレートパフェ';
if (mb_strlen($str) <= 30) // 結果:true

みたいな感じ

mb_strlenmbはマルチバイトの頭文字、日本語で使う平仮名・片仮名・漢字は基本マルチバイト文字なので日本のサイトの場合はmb_strlenを使う
MySQLはデータ型によっては文字数上限が決まっているものがある(varcharの256とかintの11とか)があるので、それらで格納するデータは文字数チェックをきちんとやってあげる必要がある
あとはパスワードとかは最低文字列を決めてあげたほうがセキュリティ的によろしいよね

正規表現

正規表現で使うのはpreg_match()、返してくる値はint(※boolではない!)

<?php
// 例:半角英数字かチェック
preg_match('/^[a-zA-Z0-9]+$/', 'HappyNewYear'); // 結果:1
preg_match('/^[a-zA-Z0-9]+$/', 'もやし'); // 結果:0

一致すれば1、不一致なら0、エラーが起こった場合にfalseを返す
正規表現パターンはシングルクォート''で囲って記述するけど、PHPの場合その後更にデリミタというもので囲ってあげる必要がある
デリミタは基本的には(上の例でも使ったように)スラッシュ/が多いみたいだけど場合によっては正規表現内に/を使う場合もあると思う(URLとか……)
そういう場合に#とか~を使ってもいい、割といろいろな文字が使えるようなので状況に応じて臨機応変に対応しよう
ちなみにデリミタの後ろにアルファベット1文字のパターン修飾子というものをつけることも出来る、一番良く使うのは文字コードUTF-8を扱う場合のu 日本語を扱う場合は必須っぽい?

大体の場合は使うパターン決まってると思うのでコピペになるでしょうね
今適当に探したサイト
PHP正規表現 英数字変換・バリデーション・漢字カタカナひらがな・メールアドレス判定
PHPでよく使うバリデーションまとめ!! | ecvoo
PHP正規表現はなんかQiitaとかでもいろいろ議論になっているようで初心者はわからん

データベースとの重複

メールアドレスとかIDとかみたいに複数ユーザーでダブっちゃだめな値はデータベースに接続して既にその値がないか確認する必要がある
SQLならSELECT count(*)で該当する条件の数を数えさせるのがいいのかな、この場合0じゃなければ既にデータが存在するという判定になるね

具体的にどの項目でどんなバリデーションチェックをすればいいかを考えてみた

メールアドレス

  • 文字数チェック(DB上限)
  • 重複チェック(メールアドレスをログイン等で使う場合でなければ要らない)
  • 形式チェック(でもメールアドレスの正規表現による完全なバリデーションは不可能らしいですね、HTML5のinputでも出来るのでこれと併用してもいいかも)

パスワード

  • 文字数チェック(DB上限もそうだが、セキュリティ考えて最低文字数もチェックしたほうがいいかもね)
  • 形式チェック(半角英数字場合によっては記号とかも判定する、セキュリティのために大文字小文字両方を必ず含めないといけないとかそういう判定をすることもあるかも)
  • 登録の場合、再入力させてそれと一致してるかのチェック

ID

  • 文字数チェック(DB上限、ユニーク性も考えて最低文字数も決めてもいいかも)
  • 形式チェック(基本的には半角英数字かな)
  • 重複チェック

URL

  • 文字数チェック(DB上限)
  • 形式チェック(正規表現、日本語URLとかどうなるんやろ)

数値系の値

  • 文字数チェック(MySQLでint型の場合文字数上限は11だ)
  • 形式チェック(半角数字かどうか、JSで全角数字を半角に自動変換する仕組み組んでもいいかも)
  • 最大や最小が決まっている値であればそれを満たしているかの判定

基本的に(varcharやintみたいな文字数制限があるデータ型であれば)文字数判定は必ず行い、その後にそれぞれの形式に応じて正規表現使ったりDBに接続して重複してないかを確かめる感じの流れですかね
あと文字列以外にもチェックボックスなんかの判定もありますね(利用規約に同意するとかみたいな……)

バリデーションチェック関数を作っておく

Webサービス、何かと値を入力させる機会は非常に多いと思われるので、汎用的に使える関数を用意していたるところで(?)使い回すのが良いと思う

例えば

<!-- 例、前提としてPOST送信 -->
<div class="form">
  <div class="form__desc">ID</div>
  <input type="text" name="user_id" class="form__text">
  <div class="form__warning">
    <?php echo (!empty($error_msg['user_id'])) ? $error_msg['user_id'] : ''; ?>
  </div>
</div>

を入力欄の基本テンプレートとしてinput typeやらname属性を変えて設置しておく
あと予めエラーメッセージを収納する連想配列グローバル変数$error_msg = array();として用意しておく
で、例えば使う頻度が圧倒的に高いであろう文字数カウントなら関数を下記のように設定する

<?php
function validMaxLen($str, $key, $max = 256)
{
    if (mb_strlen($str) >= $max) {
        global $error_msg;
        $error_msg[$key] = $max . '文字以内で入力してください';
    }
}

そうしたら後はバリデーションチェックをする場面でこの関数に引数突っ込んで渡してやればいい、この例で文字列がMySQLのvarcharの上限以内かどうかのバリデーションするなら

<?php
$user_id = $_POST['user_id'];
validMaxLen($user_id , 'user_id');

って書いてやるだけで済む、不備があれば<div class="form__warning">内にエラーメッセージも表示してくれる

そんな感じ