Developer

魁!小野の塾 小さな管理機能を作ってみようの巻 第19話
2021.08.26
Lv2

魁!小野の塾 小さな管理機能を作ってみようの巻 第19話

小さな管理機能を作ってみよう 第19話

初心者向け、PHPプログラム構築講座です。
初心者といっても、PHPの勉強を少し行い、LAMP環境が自分で構築でき、少しアプリケーションを作成しているレベルを対象とします。
まったくの初心者の場合は、わからない部分が出てくると思います。
できるだけ細かく説明は入れていきますが、説明がわからない場合は、PHPやMySQLの初心者講座をご覧ください。

対象のスキルレベル

  • LAMP環境の構築
  • PHP言語が読める
  • HTML, CSS, Javascriptが少しわかる
  • Bootstrapのドキュメントをみて、HTMLが書ける
  • Ajax(非同期通信)を利用したことがある
  • SESSIONを利用したことがある

構築環境

  • Windows10
  • XAMPP(PHP7.3.2, MariaDB 10.1.38)

共通のJavascriptを実装

今回の通信は、submitではなく、非同期通信で行います。まとめて処理を書きたいので、共通のJavascriptを整備して行きたいと思います。
Controller側で必要なのは、2つのパラメータになります。

  1. process クラス名で、拡張子(.php)をつけるとファイル名
  2. method 関数名 クラスの中の関数名になります

2つのパラメータを送信しないと、処理が実行されない仕掛けになっています。
パラメータは、metaタグに値として入れようかと思います。(hiddenでも良いのですが、今回はあまり関係ないのでmetaタグにします)

早速非同期部分の共通化に着手しようと思います。

assets/js/script.js

まず、非同期部分のコードから追記していきます。

/assets/js/script.js(抜粋)
/* XHR */
/* xhrのパス(URL)を記載します。index.phpがある部分を対象にしています。 */
var api	= '/pjin/admin/api/';
function _$xhr(data, callback){
	/* 全体をtry-catchで囲む必要はあまりないですが、念のため */
	try{
		$.ajax({
			url: api,
			type: 'POST',	/* http method は POST 限定 */
			data: data,
			dataType: 'json'
		}).done((json, status, xhr) => {
			/* 内容をconsoleに出力 */
			console.log('done', json, status, xhr);
			/* trait(Result)の定義でstatusがあるので、成功したか確認 */
			if(json.status == 'success'){
				/* 成功した場合は、callback関数を実行 */
				callback(json);
			}else{
				/* アプリケーションで失敗した場合は、画面にエラーを表示 */
				displayError(json.errors);
			}
		}).fail((xhr, status) => {
			/* そもそも非同期通信に失敗、画面にエラーを表示 */
			console.log('fail', xhr, status);
			displayError(status);
		}).always(() => {
			/* ここは成功時も失敗時も必ず通る */
			console.log('always');
		});
	}catch($e){
		/* jQueryのCDN未指定などの場合にここに来ます。 */
		console.log($e);
	}
}
/* エラーを表示します */
function displayError(status){
	/* エラーメッセージのテンプレート */
	var $alert	= [
		'<div class="alert alert-danger" role="alert" style="text-align:left;">',
		'	<h3><i class="fas fa-exclamation-triangle"></i> ERROR</h3>',
		'	<hr>',
		'	%alertMessage%',
		'</div>',
	].join('');
	/* statusの型チェック */
	if($.type(status) == 'object'){
		/* objectの場合は、キー、値の組み合わせに変更 */
		var items = Object.entries(status).map(([key, value]) => ({key, value}));
		var alertMessage	= '';
		/* 全てのメッセージを出力します */
		$.each(items, function(idx, el){
			alertMessage	+= '<p class="ps-3">'+el['value']+'</p>';
		});
		/* テンプレートから%alertMessage%の部分を置換します */
		$alert	= $alert.replace('%alertMessage%', alertMessage);
	}else{
		/* テンプレートから%alertMessage%の部分を置換します */
		$alert	= $alert.replace('%alertMessage%', '<p class="ps-3">'+status+'</p>');
	}
	/* class="error" と指定がある要素にエラー情報を追加します。 */
	$('.error').append($alert);
}

大きく2つの関数を定義しています。

  1. _$xhr(data, callback)
  2. displayError(status)

_$xhr(data, callback) は非同期通信部分を担当しています。引数は2つで、dataはFORM要素をserializeArray()したもの又は、{name: ‘name’, value: ‘value’} の形式で配列を想定しています。
また、index.php(リクエストの受け口)は、processmethod を受取ることを前提としているので、[{‘name’: ‘process’, ‘value’: ‘index’},{‘name’: ‘method’, ‘value’: ‘doMain’}] とControllerのファイル名とメソッド名が入っていることを想定しています。
callbackは非同期通信終了後に引数としてレスポンスのjsonを受取る関数を想定しています。関数の最初に _ を入れているのはシステムで利用しますよ!とかprivateですよとかいう意味で利用することが多いです。

displayError(status) は非同期通信部分の失敗(アプリケーションのチェックによる失敗や、非同期通信での失敗)時に、画面にエラーを表示する関数です。

続いて、processとmethodを決定する部分の共通化をしていきたいと思います。また、非同期通信部分の共通化を行います。

/assets/js/script.js(抜粋)
/* プロセスの決定(Controllerファイル名) */
function $process(process){
	/* metaタグに持つ予定なので、メタタグのcontentにセット */
	$('meta[name=process]').attr('content', process);
}
/* メソッドの決定(Controller内の関数名) */
function $method(method){
	/* metaタグに持つ予定なので、メタタグのcontentにセット */
	$('meta[name=method]').attr('content', method);
}
/* $paramは非同期通信で送信するオブジェクト(FORM要素ないのserializeArrayしたもの */
function routeControl($param){
	/* metaタグに設定してあるprocessとmethodを送信データに追加します */
	$param.push({'name': 'process', 'value': $('meta[name=process]').attr('content')});
	$param.push({'name': 'method', 'value': $('meta[name=method]').attr('content')});
	return $param;
}
/* validation */
function validation($forms){
	var result	= true;
	/* FORM要素分ループします */
	$forms.each(function(idx, form){
		/* 各要素(input, select, textarea)のcheckValidityを実行 */
		if (!form.checkValidity()) {
			/* エラーがある場合は、falseを返却 */
			result	= false;
		}
		/* 要素にwas-validated(validation終了)のクラスを追加 */
		$(form).addClass('was-validated');
	});
	return result;
}
/* 非同期通信の呼び出し部分 */
function $xhr($form, callback){
	/* 送信するデータはFORM要素 + process + method */
	var data	= routeControl($form.serializeArray());
	/* エラー表示領域をクリア */
	$('.error').empty();
	/* 入力チェックを実施 */
	if(!validation($form)){
		/* 入力チェックがNGの場合は、終了 */
		return false;
	}
	/* 入力チェックOKの場合は、非同期通信を実行 */
	_$xhr(data, callback);
}

今回は、5つのメソッドを追加しています。

  1. $process(process)
  2. $method(method)
  3. routeControl($param)
  4. validation($forms)
  5. $xhr($form, callback)

$process(process) metaタグにprocessを設定 ※HTMLには後程metaタグを追加する

$method(method) metaタグにmethodを設定 ※HTMLには後程metaタグを追加する

routeControl($param) metaタグに設定された、processとmethodを、非同期の送信パラメータに追加します。配列なのでpushして、形式を{name: ‘name’, value: ‘value’}にしています。

validation($forms) bootstrap標準のValidationの仕掛けをjQueryで書き直し、実行できるようにしたものです。

$xhr($form, callback) 非同期通信を受取ります。$form はFORM要素を受取ります。毎回 serializeArray を呼ぶのが面倒なので共通化。また、processとmethodを送信パラメータに追加。Validation(入力値チェック)を実施後、送信処理を実行。

ここまでで、ひとまず非同期通信のJavascriptは実装が完了しました。
ログインから順番に実装していきたいのですが、ユーザ情報のパスワードは暗号化されているため、パスワードをPHPで作成し、登録する必要があります。
ですので、一番最初は、ユーザを登録する部分から実装していきたいと思います。
きりが良いので、今回はここまでとします。

魁!小野の塾