フロント・サーバ両方にバリデーションをかける

今回はバリデーションにまつわるお話。

バリデーションとは、入力データに対して文法を規定し、あらかじめ要求した(された)ルール・仕様に則って記述されているかどうかの妥当性を検証する作業です。

入力フォームを使ったWebシステムを動かすうえで、避けては通れない機能であり、この仕組みを利用することによって、入力データの中身(というよりは形)を意図したものに導きやすくなり、想定外の入力ミスを劇的に減少させることが可能となります。

今回は文字数にフォーカスを当てて、フロントとサーバの両面でバリデーションの動かし方を見ていきましょう。

# 目次
- バリデーションを両方に設置する妥当性について
- フロントサイドでかけてみる
- サーバサイドでかけてみる
- 2つを同時にかけてみる


# バリデーションを両方に設置する妥当性について

バリデーションの構造に足を踏み入れる前に、実際のシステムでバリデーションがどのような形で用いられているかについてお話します。

現在、この世で動いているシステムのほとんどは、一つの入力フォームに対して、フロントとサーバ両方でバリデーションをかけていて、その用法が主流のようです。

どういうことかというと、一つの入力データに対して、フロント、そしてサーバと2つの側面からチェックを働かせているのです。
この2つがそれぞれ別の要素・ルール・規定に基づいて別個のチェックを行なっているのであれば腑に落ちるのですが、現実は同じ要素・ルール・規定を以て同じ個所にアプローチがかけられています。

一気に2方向からチェックをかけなくてもどちらか一方が正常に働ければ、それで全く問題ないのですが、多くのシステムではそのような設計で動いていません。もしもどちらかが不具合で動かなかったとしても、別の機能が働くことでシステム上のミスを未然に防ぐことができます。そして相互に強固な補完関係を実装させることで、より安全で正確なデータの取り扱いが可能となるのです。

要はおまじないみたいなものです。それでは本題に入っていきます。
まずは入力フォームを簡単に作ってまいります。

```php:input.php
<form action= "input.php" name="regist" method="post">
  入力フォーム:<input type="text" name="input" value="">
  <input type="button" value="送信" onClick="confirm()">
</form>
```
![input.jpg](https://qiita-image-store.s3.amazonaws.com/0/258818/7197bada-797e-1f5a-b38a-63c73e5b75e3.jpeg)

今回、サーバ側言語はPHPを使います。
そしてバリデーションのルールは**1文字以上10文字以内**という規則を設けて機能性を探っていきます。
そのため空欄、もしくは11文字以上の記述に対してエラーメッセージの表示を実装します。

JavaScriptとPHP、この2つからそれぞれのバリデーションの動きに迫っていきましょう。

# フロントサイドでかけてみる

フロントサイドでのバリデーションといえば、ボタンクリックによるイベント発火のタイミングがまず思い出されます。

上記ソースで送信ボタンを構成するinputタグを参照してください。
type属性にbuttonを指定し、onClick属性で処理(confirm())を呼び出します。
ではconfirm()に正しい規則に則った機能を実装していきましょう。

```php:input.php
<script language="javascript">
  function confirm(){
    if(document.regist.input.value.length < 1 || document.regist.input.value.length > 10){
      alert('1文字以上10文字以内で入力してください。');
      document.regist.input.focus();
      return;
    }
    if(confirm('正しいルールで記述されています。')){
      document.new_regist.submit();
    }
  }
  </script>
```

formタグ(regist)内の入力フォーム(input)で入力された文字列(value)の長さ(length)が1文字未満(<1)、もしくは(||)11文字以上(>10)になった場合はalertを出す仕組みで構築してみました。

実際に動かしてみましょう。

![input1.jpg](https://qiita-image-store.s3.amazonaws.com/0/258818/4e55086a-a10d-13de-cfc0-ea276746cd86.jpeg)


![input2.jpg](https://qiita-image-store.s3.amazonaws.com/0/258818/4bad7259-0700-2340-27ef-d365acb732ba.jpeg)

静止画ではわかりづらいですが、イベント発火のタイミングでしっかりバリデーションチェックが働き、alertが表示されました。

# サーバサイドでかけてみる
次はサーバサイドでバリデーションをかけてみましょう。

サーバサイドでもバリデーションのかけ方は基本的にフロントサイドと似ています。

入力データの文字数を取得して、それを条件分岐によって判定していく、という過程です。
しかしタイミングが異なります。まずは処理を実装していきましょう。

```php:input.php
$input = $_POST['input'];
$count_input = mb_strlen($input);

if($count_input < 1 || $count_input > 10){
   echo '判定結果:1文字以上10文字以内で入力してください。';
} else {
   echo '判定結果:正しいルールで記述されています。';
}
```

一番最初に掲載したソースにおいて、フォームに記述された入力データは同じ画面(input.php)にpost送信される仕組みでコーディングされています。

$__POSTで受け取った入力データをmb_strlen()関数の引数にして、文字数を取得し、フロントサイドと同様に条件分岐で判定されます。
ではこちらの動きも見てみましょう。

![input1.jpg](https://qiita-image-store.s3.amazonaws.com/0/258818/6bb84e31-a344-aa54-f07e-7cdf9d208163.jpeg)

![input3.jpg](https://qiita-image-store.s3.amazonaws.com/0/258818/211f7318-94cc-0765-c095-ac538f3c5d95.jpeg)

ソースの通り、値をリクエストで受け取ったタイミングでしっかりバリデーションチェックが機能しました。

# 2つを同時にかけてみる

フロントサイドではイベント発生のタイミングで、サーバサイドではリクエストを受け取ったタイミングで、それぞれバリデーションがかけられました。

ではこれらの処理を同時にかけた場合、どちらの処理が先に行なわれるのでしょうか。

```php:input.php
<script language="javascript">
  function confirm(){
    if(document.regist.input.value.length < 1 || document.regist.input.value.length > 10){
      alert('1文字以上10文字以内で入力してください。');
      document.regist.input.focus();
      return;
    }
    if(confirm('正しいルールで記述されています。')){
      document.new_regist.submit();
    }
  }
  </script>

<?php
$input = $_POST['input'];
$count_input = mb_strlen($input);

if($count_input < 1 || $count_input > 10){
   echo '判定結果:1文字以上10文字以内で入力してください。';
} else {
   echo '判定結果:正しいルールで記述されています。';
}
 ?>
```

結果はいうまでもないと思いますが、念のため動きを見てみましょう。

![input4.jpg](https://qiita-image-store.s3.amazonaws.com/0/258818/1f045b4b-6cb9-71b6-d877-4f806152665e.jpeg)

当然ながらボタンクリックの時点でチェック機能が発動するフロントサイドの処理が先に行なわれました。
ただ万が一、フロントサイドの処理が正常に動かなかった場合でも(そんなことあってはならないのですが)、サーバサイドで補完処理が行なわれるので、安全で正確なシステム運営が期待できます。

# ひとりごと

最大文字数を例に今回のエントリーを進めてきましたが、「そもそもHTMLにmaxlengthをかませてしまえばすぐに解決する」という意見があることは重々承知で投稿しました。

めくるめくシステムの多面性。一つの事象を解決するための方法論が複数存在するということは、頼もしくもありますが、見方を変えれば最適解は何になるか？という問いも投げかけられます。

答えを複数個用意すること、その中から最適解を選ぶこと。

テーマがおぼろげながら形になってまいりました。ただそこに辿りつくまではまだまだ時間を要しそうです。