Developer

魁!小野の塾 PHPで簡単なプログラムを作ってみようの巻 第8話
2021.01.01
Lv2

魁!小野の塾 PHPで簡単なプログラムを作ってみようの巻 第8話

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 をクラスに追加すると緑枠になります。

魁!小野の塾