前々回の「テーブルデータの表示」をMVCモデル構成にしたうえで、ページング機能を追加しました。
MVCモデル構成については前回の掲載を参照してください。
まず、ページングの画面サンプルです。

続いて、コードを掲載します。
次の順番でコードを掲載します。
1. ブラウザ要求をコントローラーの適切な処理へ橋渡しするコード
PagingTestEntry.php
PagingTestReceipRequest.php
2. コントローラーのコード
PagingTestController.php
3. モデルのコード
SessionModel.php
PDOModel.php
PagingModel.php
4. ビューのコード
PagingTestView.php
PagingTestEndView.html
PagingTestEntry.php
<?php
/*************************************************
* Enty point
* ブラウザからhttp://****.php.xdomain.jp/PagingTestEntry.php
* で呼ばれる最初の起動プログラム
* コントローラー(PagingTestController.PHP)のrunメソッドを呼び出します
*/
require_once( __DIR__ . '/PagingTestController.php');
$controller = new PagingTestController();
$controller->run();
exit;
?>
PagingTestReceiveRequest.php
<?php
/*************************************************
* PagingTestView.phpのPOSTリクエストを受取り、
* コントローラー(PagingTestController.php)の
* handleRequest()メソッドを呼び出します
*/
require_once __DIR__ . '/PagingTestController.php';
$controller = new PagingTestController();
$controller->handleRequest();
exit;
?>
PagingTestController.php
<?php
/**
* Description of PagingTestController
* Userテーブルの表示画面に対するコントローラーの役割
*
*/
class PagingTestController{
//クラス変数を定義します
private $table_data = []; //userテーブルデータを保持する配列変数
private $paging_info = []; //ページング情報を保持する配列変数
private $session_model; //SessionModelのインスタンスを保持
private $pdo_model; //PDOMdelのインスタンスを保持
private $paging_model; //PagingModelインスタンスを保持
//コンストラクター
public function __construct() {
require_once(__DIR__ . '/SessionModel.php');
require_once(__DIR__ . '/PDOModel.php');
require_once(__DIR__ . '/PagingModel.php');
//Modelクラスのインスタンスを生成します
$this->session_model = new SessionModel();
$this->pdo_model = new PDOModel();
$this->paging_model = new PagingModel();
}
/******************************************************
* 当メソッドはPagingTestEntry.phpから呼ばれます
* Userテーブルデータを最初に画面表示する処理を行います
*****************************************************/
public function run() {
ob_start(); // 出力バッファリングを有効にします
$this->session_model->sessionstart(); //セッションを開始します
$this->pdo_model->db_connect(); //データベースに接続します
$this->table_data = $this->pdo_model->select_usertable(); //Userテーブルデータを取得し、その返り値を配列に代入します
$this->session_model->set_user_table($this->table_data); //Userテーブルデータをセッションに保管します
$this->paging_info = $this->paging_model->init($this->table_data); //初回に表示するページングの値を求めます
$this->session_model->set_paging_info($this->paging_info); //ページングのデータをセッションに保管します
header('Location: PagingTestView.php'); //Userデータ表示ページ(PagingTestView.php)へリダイレクトします
ob_end_flush(); // 出力バッファをフラッシュして終了します
exit();
}
/******************************************************
* 当メソッドはPagingTestRecieveRequest.phpから呼ばれます
* [次ページ]、[前ページ]、[終了]ボタンが選択された時の
* POSTリクエストの処理を行います
*****************************************************/
public function handleRequest() {
$this->session_model->sessionstart(); //セッションを再開します
//セッションに保持したUserテーブルデータとページングのデータを取り出します
$this->table_data = $this->session_model->get_user_table();
$this->paging_info = $this->session_model->get_paging_info();
//「終了」ボタンのPOSTリクエストの処理
if (isset($_POST['end']) && $_POST['end'] == "終了") {
// セッション変数を空にします
$_SESSION = [];
// クッキーを削除します
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
// セッションを破壊します
session_destroy();
//終了ページ(PagingTestEndView.php)へリダイレクトします
header('Location: PagingTestEndView.html');
//「前ページ」ボタンのPOSTリクエストの処理
} elseif (isset($_POST['back']) && $_POST['back'] == "≪前ページ") {
//前ページのページング情報を算出し、その情報を得ます
$this->paging_info = $this->paging_model->back($this->paging_info);
//前ページングのページング情報をセッションに保管します
$this->session_model->set_paging_info($this->paging_info);
//Userデータ表示ページ(PagingTestView.php)へリダイレクトします
header('Location: PagingTestView.php');
//「次ページ」ボタンのPOSTリクエストの処理
} elseif (isset($_POST['next']) && $_POST['next'] == "次ページ≫") {
//次ページのページング情報を算出し、その情報を得ます
$this->paging_info = $this->paging_model->next($this->paging_info);
//次ページングのページング情報をセッションに保管します
$this->session_model->set_paging_info($this->paging_info);
//Userデータ表示ページ(PagingTestView.php)へリダイレクトします
header('Location: PagingTestView.php');
}
}
}
?>
SessionMode.php
<?php
/**
* Description of SessionModel
* セッションに係る次の処理を受け持つクラスです
*
* セッションの開始処理とセッションへのデータ保管や取出し
* を行います
*
*/
class SessionModel {
//クラス変数を定義します
protected $sessname = 'PHPSESSION_MEMBER'; //セッション名を「PHPSESSION_MEMBER」にします
protected $table_data = []; //userテーブルデータを保持する配列変数
protected $paging_info = []; //ページング情報を保持する配列変数
//*****************************************************
// コンストラクター
//*****************************************************
public function __construct() {
}
//*****************************************************
// セッションの開始処理をします
//*****************************************************
public function sessionstart() {
if (session_status() != PHP_SESSION_ACTIVE) {
// セッションが非アクティブならセッションを開始します
if ($this->sessname != "") {
//セッション名を確実に「PHPSESSION_MEMBE」するためのコードです
session_name($this->sessname);
}
session_start(); // セッション開始
}
return;
}
//*****************************************************
// userテーブルデータをセッションに保管します
//*****************************************************
public function set_user_table(array $table_data) {
$this->table_data = $table_data;
// セッション変数(ses_table_data)を削除します
unset($_SESSION['ses_table_data']);
// userテーブルデータをセッション変数(ses_table_data)に保管します
$_SESSION['ses_table_data'] = $this->table_data;
return;
}
//*****************************************************
// Userテーブルデータをセッションから取り出します
//*****************************************************
public function get_user_table() {
// セッションからuserテーブルデータを取り出します
$this->table_data = isset($_SESSION['ses_table_data']) ? $_SESSION['ses_table_data'] : [];
// 取り出したuserテーブルデータを返します
return $this->table_data;
}
//*****************************************************
// ページング情報をセッションに保管します
//*****************************************************
public function set_paging_info(array $paging_info) {
$this->paging_info = $paging_info;
// セッション変数(ses_paging_info)を削除します
unset($_SESSION['ses_paging_info']);
// ページング情報をセッション変数(ses_paging_info)に保管します
$_SESSION['ses_paging_info'] = $this->paging_info;
return;
}
//*****************************************************
// ページング情報をセッションから取り出します
//*****************************************************
public function get_paging_info() {
// セッションからページング情報を取り出します
$this->paging_info = isset($_SESSION['ses_paging_info']) ? $_SESSION['ses_paging_info'] : [];
// 取り出したページング情報を返します
return $this->paging_info;
}
}
?>
PDOModel.php
<?php
/**
* Description of PDOModel
* データベースに係る処理を受け持つクラスです
*/
class PDOModel {
//クラス変数を定義します
protected $pdo; //PDOライブラリアプリのインスタンスを保持
protected $host; //ホスト情報
protected $dbname; //データベース名
protected $dbusr; //データベース接続ユーザー名
protected $dbpass; //データベース接続パスワード
protected $table_data = []; //userテーブルデータを保持する配列
//*****************************************************
// コンストラクター
//*****************************************************
public function __construct() {
// データベース接続情報を変数にセットします
$this->host = 'mysql1.php.xdomain.ne.jp';
$this->dbname = '****_receipt';
$this->dbusr = '********';
$this->dbpass = '**********';
}
//*****************************************************
// DB接続処理
//*****************************************************
public function db_connect() {
// DB接続処理
try {
$this->pdo = new PDO("mysql:host={$this->host};dbname={$this->dbname};charset=utf8", $this->dbusr, $this->dbpass);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch(PDOException $Exception) {
die('DB Connect Error: ' . $Exception->getMessage());
}
return;
}
//*****************************************************
// userテーブルへselect文発行
// 下記select文はuserテーブルからAI_Userの値が0~200のデータを取り出します
//*****************************************************
public function select_usertable() {
// select文を生成して実行します
try {
$sql= "SELECT * FROM user WHERE AI_User BETWEEN :AIFrom AND :AITo";
$stmh = $this->pdo->prepare($sql);
$stmh->bindValue(':AIFrom', 0, PDO::PARAM_INT);
$stmh->bindValue(':AITo', 200, PDO::PARAM_INT);
$stmh->execute(); //select文を実行します
// select文で抽出したデータを1行ずつ取出して$table_data[]にセットします
while($row = $stmh->fetch(PDO::FETCH_ASSOC)) {
$this->table_data[] = $row;
}
} catch (PDOException $Exception) {
die('DB select Error: ' . $Exception->getMessage());
}
// テーブルデータの配列($table_data[])を返します
return $this->table_data;
}
}
?>
PagingTestView.php
<?php
session_name('PHPSESSION_MEMBER'); // セッション名セット
session_start(); // セッション開始
// セッションからUserテーブルデータとページング情報を取り出します
$table_data = isset($_SESSION['ses_table_data']) ? $_SESSION['ses_table_data'] : [];
$paging_info = isset($_SESSION['ses_paging_info']) ? $_SESSION['ses_paging_info'] : [];
?>
<!-- Userテーブルのデータをブラウザに表示するテストプログラムです -->
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
div.main{
width: 960px;
min-height:300px;
margin:0 0 0 0;
padding:10px;
background-color:#ffffff;
}
table{border: 0; border-collapse: collapse;}
#button_area{width:100%}
h1{text-align: center; color: #002060; background-color:#F4B084; line-height: 120%}
.label2{border: solid 1px #000000; border-collapse: collapse; height: 30px;}
.label3{color: #ffffff; background-color:#305496; font-weight: 600; border: solid 1px #000000; border-collapse: collapse; text-align: center; height: 25px;}
.func_button{color:#ffffff; background-color:#4472c4; font-weight: 600; width: 80px; height: 40px;font-size:11pt;}
#back{
float : left;
text-align: left;
}
#next{
text-align : right;
}
.select_button{
line-height:20pt;
padding:2px 10px 2px 10px;
border-style: solid;
border-width: 1px;
border-color: 000000;
text-decoration:none;
font-size:11pt;
font-weight: 600;
text-align: center;
color:#800080;
border-color: 000000;
background-color:#d9d9d9;
}
</style>
<title>user table data</title>
</head>
<body>
<div class="main">
<h1>userテーブルのデータ</h1>
<form action="PagingTestReceiveRequest.php" method="post">
<table style="width:100%;">
<tr>
<th style="width:115px; text-align: center" class="label3">AI</th>
<th style="width:220px; text-align: center" class="label3">User ID</th>
<th style="width:220px; text-align: center" class="label3">パスワード</th>
<th style="width:405px; text-align: center" class="label3">名前</th>
</tr>
<?php
if($paging_info['total_record'] != 0){
for($i = $paging_info['first_record']; $i <= $paging_info['last_record']; $i++){
?>
<tr>
<td class="label2" style="text-align: center;">
<?= htmlspecialchars($table_data[$i]['AI_User']) ?>
</td>
<td class="label2" style="text-align: left;">
<?= htmlspecialchars($table_data[$i]['UID']) ?>
</td>
<td class="label2" style="text-align: left;">
<?= htmlspecialchars($table_data[$i]['password']) ?>
</td>
<td class="label2" style="text-align: left">
<?= htmlspecialchars($table_data[$i]['name']) ?>
</td>
</tr>
<?php
}
} else {
echo "<tr><td colspan='4' class='label2' style='text-align: center;'>表示するデータがありません。</td></tr>";
}
?>
</table>
<div id="back">
<?php
if($paging_info['first_record'] != 0){
?>
<input type="submit" name="back" value="≪前ページ">
<?php
}
?>
</div>
<div id="next">
<?php
if ($paging_info['last_record'] > 0 && $paging_info['last_record'] < floor(($paging_info['total_record'] - 1) / $paging_info['lines']) * $paging_info['lines']) {
?>
<input type="submit" name="next" value="次ページ≫">
<?php
}
?>
</div>
<p></p>
<table id="button_area" style="width:100%">
<tr>
<td style="width:33%; text-align: center;"></td>
<td style="text-align: center;"><input class="func_button" name="end" value="終了" type="submit" /></td>
<td style="width:33%; text-align: center;"></td>
</tr>
</table>
<table>
</table>
</form>
</div>
</body>
</html>
PagingTestEndView.php
<!-- Userテーブルのデータをブラウザに表示するテストプログラムの終了画面です -->
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
div.main{
width: 960px;
min-height:300px;
margin:0 0 0 0;
padding:10px;
background-color:#ffffff;
}
table{border: 0; border-collapse: collapse;}
#button_area{width:100%}
h1{text-align: center; color: #002060; background-color:#F4B084; line-height: 120%}
.label2{border: solid 1px #000000; border-collapse: collapse; height: 30px;}
.label3{color: #ffffff; background-color:#305496; font-weight: 600; border: solid 1px #000000; border-collapse: collapse; text-align: center; height: 25px;}
.func_button{color:#ffffff; background-color:#4472c4; font-weight: 600; width: 80px; height: 40px;font-size:11pt;}
#back{
float : left;
text-align: left;
}
#next{
text-align : right;
}
.select_button{
line-height:20pt;
padding:2px 10px 2px 10px;
border-style: solid;
border-width: 1px;
border-color: 000000;
text-decoration:none;
font-size:11pt;
font-weight: 600;
text-align: center;
color:#800080;
border-color: 000000;
background-color:#d9d9d9;
}
</style>
<title>user table data</title>
</head>
<body>
<div class="main">
<h1>終了しました</h1>
</div>
</body>
</html>
今回のWeb版レシート管理では、クラスの継承やインターフェースなどは行わない予定です。
アプリの規模が小さく、取り入れる部分がなさそうです。
プログラム構造はMVCで設計しますが、その中でコードの可読性を重視して作ることを心掛けたいと思います。
1年後、2年後に見直したときでも、すぐに全体像が理解でき、ロジックが追えるようなプログラム構造とコーディングを目指していきます。
今は、XFreeレンタルサーバーでサーバーサイドアプリの作り方を勉強中です。
大事なポイントをキチンと理解して整理しておこうと思っています。
整理したものは、私の忘備録として、順次当ブログに掲載していきます。