PHPで簡単なプログラムを作ってみよう 第8話
初心者向け、PHPプログラム構築講座です。
初心者といっても、PHPの勉強を少し行い、LAMP環境が自分で構築できるレベルを対象とします。
まったくの初心者の場合は、わからない部分が出てくると思います。
できるだけ細かく説明は入れていきますが、説明がわからない場合は、PHPやMySQLの初心者講座をご覧ください。
対象のスキルレベル
- LAMP環境の構築
- PHP言語が読める
- HTML, CSS, Javascriptが少しわかる
- Bootstrapのドキュメントをみて、HTMLが書ける
- CDNを理解している
構築環境
- Windows10
- XAMPP(PHP7.3.2, MariaDB 10.1.38)
Validation
エラーチェックを実装していきます。
処理部分と、エラーの表示部分を作成するのですが、エラーメッセージはalertとして上に表示。
エラーのある場所は、入力枠を赤くする方向です。入力枠にエラーを表示することはしません。
入力エラーの表示に関しては、魁!小野の塾 PHPで簡単なプログラムを作ってみようの巻 第4話をもう一度読み直してください。
エラーチェックは、登録時のみ実施します。今回は更新がないのと、削除の場合は存在チェックなど行うのですが、今回は行わない予定です。
<?php // db resource $db = new mysqli('localhost', 'root', '', 'pjin'); $db->set_charset("utf8"); // $_POST -> $request $request = [ 'author' => $_POST['author'] ?? '', 'content' => $_POST['content'] ?? '', 'action' => $_POST['action'] ?? '' ]; // create $errors = []; switch($request['action']){ case 'create': // error check if(empty($request['author'])){ $errors['author'][] = '名前を入力して下さい。'; } if(mb_strlen($request['author']) > 128){ $errors['author'][] = '名前は128文字以内で入力して下さい。'; } if(empty($request['content'])){ $errors['content'][] = '内容を入力して下さい。'; } if(mb_strlen($request['content']) > 65535){ $errors['content'][] = '名前は65,535文字以内で入力して下さい。'; } if(count($errors) > 0){ // エラーがあれば終了 break; } // 登録処理 $sql = "insert into board(author, content) values (?, ?)"; if($stmt = $db->prepare($sql)){ $stmt->bind_param("ss", $request['author'], $request['content']); $stmt->execute(); $stmt->close(); // 登録後に空にします。 $request = [ 'author' => '', 'content' => '' ]; } break; } // 検索処理 $rs = []; $sql = "select * from board order by id desc"; if($stmt = $db->prepare($sql)){ $stmt->execute(); $stmt->bind_result($id, $createdAt, $author, $content); while($stmt->fetch()){ $rs[] = [ 'id' => $id, 'createdAt' => $createdAt, 'author' => $author, 'content' => $content ]; } $stmt->close(); } // db resource close $db->close(); ?>
※参考 empty
※参考 mb_strlen
※参考 マルチバイト文字列 関数
もうちょっといい方法があるような気もするのですが、かなり勢いで作っているので、あまり考えないようにしています。
まず、$errors というエラー内容を入れる配列を作成します。
エラーチェックは、必須チェックと文字数制限の2種類のみ実施します。
実際は、半角、全角のみのチェックなど色々と入れるのですが、データの種類も数字や日付がないので、簡単なエラーチェックだけ実装しています。
必須チェックは、empty関数を利用して行います。
※参考 PHP isset, empty, is_null の違い早見表
参考サイトを見てみると、empty関数では、0を未入力として判断します。実際半角0を入力するケースは想定していないので、この仕様で良しとします。
文字数チェックは、マルチバイト関数で、文字数をカウントします。
MySQLもvarcharで指定している長さは文字数となりますので、長さでチェックします。
textは65,535文字を登録することが可能です。文字数がこの長さを超える場合は、mediumtext やlongtext という型もあります。文字数がやばいことに。。
$errorsの内容は2次元配列になっています。1次元目は、連想配列なので、author又はcontentになり、それぞれの項目に対して、0,1とエラーを入れることができます。
実際のところは、入っていない又は文字数制限超えのどちらかしか入りませんが。。。
プログラムから$errorsの内容を表してみると以下の表になります。
author | [0] | 未入力 |
author | [1] | 文字数制限 |
content | [0] | 未入力 |
content | [1] | 文字数制限 |
ただ、2次元配列として内容を表すと以下のようになります。
[0] | [1] | |
---|---|---|
author | 未入力 | 文字数制限 |
content | 未入力 | 文字数制限 |
なぜ2次元配列にしているかというと、項目毎(author, content)にエラーがあるかをチェックできるようにしたいからです。
配列は空で初期化しているので、どこかのエラーチェックにひっかかると、1次元目の項目が追加されます。これで、$errorsの配列の要素数が0よりも大きくなれば、エラーが発生していることが分かります。
HTML部分の修正
エラー部分は、alertで出力し、各項目を赤枠で表示するようにします。
<main class="container"> <?php if(count($errors) > 0){ ?> <div class="alert alert-danger" role="alert"> <h4 class="alert-heading"><i class="fas fa-exclamation-triangle"></i> エラー</h4> <ul> <?php foreach($errors as $err){ ?> <?php foreach($err as $e){ ?> <li><?php echo htmlentities($e) ?></li> <?php } ?> <?php } ?> </ul> </div> <?php } ?> <form action="<?php echo $_SERVER['SCRIPT_NAME'] ?>" method="POST"> <input type="hidden" name="action" value="create"> <div class="form-group row"> <label for="author" class="col-sm-2 col-form-label">名前</label> <div class="col-sm-10"> <input type="text" name="author" id="author" value="<?php echo $request['author'] ?>" class="form-control<?php if(isset($errors['author'])){ echo ' is-invalid';} ?>" placeholder="名前" autofocus> </div> </div> <div class="form-group row"> <label for="content" class="col-sm-2 col-form-label">内容</label> <div class="col-sm-10"> <textarea name="content" id="content" class="form-control<?php if(isset($errors['content'])){ echo ' is-invalid';} ?>" rows="10" placeholder="内容を入力してください"><?php echo $request['content'] ?></textarea> </div> </div> <div class="form-group row"> <div class="offset-sm-2 col-sm-10"> <button type="submit" class="btn btn-primary"><i class="fas fa-paper-plane"></i> 送信</button> </div> </div> </form>
3行目~14行目までが、alert部分の表記になります。(class=”alert alert-danger”)
$errorsの配列数が0よりも大きい(エラーがある場合)に表示するようにします。
$errorsは2次元配列になっているため、内容を出力する場合は、ループをネスト(入れ子)にします。
7、8行目が foreach をネストして、内容を表示する部分になります。
23行目、31行目は、入力枠部分を赤く表示するために、エラーがある場合に class を付加しています。(is-invalid)
is-invalid をクラスに追加すると、赤枠に、is-valid をクラスに追加すると緑枠になります。