はじめに
今回は、PHPとMySQLを使ってMVCモデルでCRUD機能を実装していきます。
CRUD機能とは?
ほぼ全てのソフトウェアが有する4つの永続的な基本機能の頭文字をそれぞれ並べた用語のこと。
その4つの機能とは、Create(生成)、Read(読み取り)、Update(更新)、Delete(削除)。
バージョン
PHP:7.4.5
phpMyAdmin:5.0.2
MySQL:5.7.30
今回作成するファイル
conf / html / model / view の4つのディレクトリを作って進めます。
conf(繰り返し使用するものを定義)
- const.php
html(controller)
- admin.php
- admin_insert.php
- admin_update_stock.php
- admin_delete.php
model
- db.php
- functions.php
- items.php
view
- admin_view.php
テーブルの作成
CREATE TABLE `sample_items` (
`item_id` int(11) NOT NULL,
`name` varchar(100) NOT NULL,
`price` int(11) NOT NULL,
`stock` int(11) NOT NULL,
`created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
ALTER TABLE `sample_items`
MODIFY `item_id` int(11) NOT NULL AUTO_INCREMENT,
ADD PRIMARY KEY (`item_id`);
定義
<?php
// ディレクトリパス
define('MODEL_PATH', $_SERVER['DOCUMENT_ROOT'] . '/../model/');
define('VIEW_PATH', $_SERVER['DOCUMENT_ROOT'] . '/../view/');
// MySQL接続用
define('DB_HOST', 'ホスト名');
define('DB_NAME', 'データベース名');
define('DB_USER', 'ユーザ名');
define('DB_PASS', 'パスワード');
define('DB_CHARSET', 'utf8');
// URL
define('ADMIN_URL', '/admin.php');
Viewの作成
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>商品管理</title>
</head>
<body>
<h1>商品管理ページ</h1>
<form method="post">
<div>
<label>名前</label>
<input type="text" name="name">
</div>
<div>
<label>価格</label>
<input type="number" name="price">
</div>
<div>
<label>在庫</label>
<input type="number" name="stock">
</div>
<input type="submit" value="送信">
</form>
<!-- 表示 -->
<table>
<thead>
<tr>
<th>名前</th>
<th>価格</th>
<th>在庫</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</body>
</html>
Create機能の実装
Modelの作成
db.phpを作成(データベース関係)
<?php
function get_db_connect(){
// MySQL用のDSN文字列
$dsn = 'mysql:dbname='. DB_NAME. ';host='. DB_HOST. ';charset='. DB_CHARSET;
try{
// DB接続
$dbh = new PDO($dsn, DB_USER, DB_PASS, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4'));
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
}catch(PDOException $e){
exit('接続できませんでした。理由:'.$e->getMessage());
}
return $dbh;
}
function execute_query($db, $sql, $params = array()){
try{
$statement = $db->prepare($sql);
return $statement->execute($params);
}catch(PDOException $e){
set_error('更新に失敗しました。');
}
return false;
}
functions.phpを作成(その他機能)
<?php
function redirect_to($url){
header('Location:'. $url);
exit;
}
function get_post($name){
if(isset($_POST[$name]) === true){
return $_POST[$name];
};
return '';
}
// セッション
function get_session($name){
if(isset($_SESSION[$name]) === true){
return $_SESSION[$name];
};
return '';
}
function set_session($name, $value){
$_SESSION[$name] = $value;
}
// エラーメッセージ
function set_error($error){
$_SESSION['__errors'][] = $error;
}
function get_errors(){
$errors = get_session('__errors');
if($errors === ''){
return array();
}
set_session('__errors', array());
return $errors;
}
// メッセージ
function set_message($message){
$_SESSION['__message'][] = $message;
}
function get_messages(){
$messages = get_session('__message');
if($messages === ''){
return array();
}
set_session('__message', array());
return $messages;
}
items.phpを作成(商品関係)
<?php
require_once MODEL_PATH. 'functions.php';
require_once MODEL_PATH. 'db.php';
// Create
function regist_item($db, $name, $price, $stock){
$sql = "
INSERT INTO
sample_items(
name,
price,
stock
)
VALUES(?,?,?)
";
return execute_query($db, $sql, array($name, $price, $stock));
}
Viewの作成
admin_view.phpにCreate処理へ遷移するよう追記
- 処理結果を表示できるよう追記
- formタグにactionを追記
<!-- 処理結果のメッセージ -->
<?php foreach(get_errors() as $error){ ?>
<p><?php print $error; ?></p>
<?php } ?>
<?php foreach(get_messages() as $messages){ ?>
<p><?php print $messages; ?></p>
<?php } ?>
<!-- 投稿フォーム -->
<form method="post" action="admin_insert.php">
<div>
<label>名前</label>
<input type="text" name="name">
</div>
<div>
<label>価格</label>
<input type="number" name="price">
</div>
<div>
<label>在庫</label>
<input type="number" name="stock">
</div>
<input type="submit" value="送信">
</form>
Controllerの作成
admin.phpを作成(admin_view.php表示用)
<?php
require_once '../conf/const.php';
require_once MODEL_PATH. 'items.php';
session_start();
include_once VIEW_PATH. 'admin_view.php';
admin_insert.phpを作成(Insert処理用)
<?php
require_once '../conf/const.php';
require_once MODEL_PATH. 'functions.php';
require_once MODEL_PATH. 'bbs.php';
session_start();
// データベース接続
$db = get_db_connect();
// Postされたものを定義
$name = get_post('name');
$price = get_post('price');
$stock = get_post('stock');
// Insert
if(regist_item($db, $name, $price, $stock)){
set_message('商品を登録しました。');
}else{
set_error('商品の登録に失敗しました。');
}
redirect_to(ADMIN_URL);
Read機能の実装
Createで挿入されたデータを表示されるようにしていきます。
Modelの作成
db.phpにRead機能を追記
function fetch_all_query($db, $sql, $params = array()){
try{
$statement = $db->prepare($sql);
$statement->execute($params);
return $statement->fetchAll();
}catch(PDOException $e){
set_error('データ取得に失敗しました。');
}
return false;
}
items.phpに追記
// Read
function get_items($db){
$sql = "
SELECT
item_id,
name,
price,
stock
FROM
sample_items
";
return fetch_all_query($db, $sql);
}
Viewの作成
admin_view.phpに追記
- tableタグ内のtbodyタグに追記
<tbody>
<?php foreach($items as $item){ ?>
<tr>
<td><?php print($item['name']); ?></td>
<td><?php print($item['price']); ?></td>
<td><?php print($item['stock']); ?></td>
<td></td>
</tr>
<?php } ?>
</tbody>
Controllerの作成
<?php
require_once '../conf/const.php';
require_once MODEL_PATH. 'items.php';
session_start();
// SELECT文で選択したデータを表示させる為に追記
$db = get_db_connect();
$items = get_items($db);
include_once VIEW_PATH. 'admin_view.php';
Update機能の実装
Createで生成されたデータを変更できるようにしていきます。
Modelの作成
items.phpにUpdate機能を追記
// Update
function update_stock($db, $item_id, $stock){
$sql = "
UPDATE
sample_items
SET
stock = ?
WHERE
item_id = ?
";
return execute_query($db, $sql, array($stock, $item_id));
}
Viewの作成
admin_view.phpにUpdate処理へ遷移するよう追記
- tableタグ内のtbodyに追記
<tbody>
<?php foreach($items as $item){ ?>
<tr>
<td><?php print($item['name']); ?></td>
<td><?php print($item['price']); ?></td>
<td>
<form method="post" action="admin_update_stock.php">
<input type="number" name="stock" value="<?php print($item['stock']); ?>">
<input type="submit" value="変更">
<input type="hidden" name="item_id" value="<?php print($item['item_id']); ?>">
</form>
</td>
<td></td>
</tr>
<?php } ?>
</tbody>
Controllerの作成
admin_update_stock.phpを作成(Update処理用)
<?php
require_once '../conf/const.php';
require_once MODEL_PATH. 'functions.php';
require_once MODEL_PATH. 'items.php';
session_start();
// データベース接続
$db = get_db_connect();
// Postされたものを定義
$item_id = get_post('item_id');
$stock = get_post('stock');
// Update
if(update_stock($db, $item_id, $stock)){
set_message('在庫を更新しました。');
} else {
set_error('在庫の更新に失敗しました。');
}
redirect_to(ADMIN_URL);
Delete機能の実装
Createで生成されたデータを削除できるようにしていきます。
Modelの作成
items.phpにDelete機能を追記
// Delete
function delete_item($db, $item_id){
$sql = "
DELETE FROM
sample_items
WHERE
item_id = ?
";
return execute_query($db, $sql, array($item_id));
}
Viewの作成
admin_view.phpにDelete処理へ遷移するよう追記
- tableタグ内のtbodyに追記
<tbody>
<?php foreach($items as $item){ ?>
<tr>
<td><?php print($item['name']); ?></td>
<td><?php print($item['price']); ?></td>
<td>
<form method="post" action="admin_update_stock.php">
<input type="number" name="stock" value="<?php print($item['stock']); ?>">
<input type="submit" value="変更">
<input type="hidden" name="item_id" value="<?php print($item['item_id']); ?>">
</form>
</td>
<td>
<form method="post" action="admin_delete.php">
<input type="submit" value="削除">
<input type="hidden" name="item_id" value="<?php print($item['item_id']); ?>">
</form>
</td>
</tr>
<?php } ?>
</tbody>
Controllerの作成
admin_delete.phpを作成(Delete処理用)
<?php
require_once '../conf/const.php';
require_once MODEL_PATH. 'functions.php';
require_once MODEL_PATH. 'items.php';
session_start();
// データベース接続
$db = get_db_connect();
// Postされたものを定義
$item_id = get_post('item_id');
// Delete
if(delete_item($db, $item_id)){
set_message('商品を削除しました。');
} else {
set_error('商品の削除に失敗しました。');
}
redirect_to(ADMIN_URL);