はじめに
今回は、カート機能を実装していきます。
※当ページは、【PHPでECサイト】で作られたものを前提にしています。
バージョン
PHP:7.4.5
phpMyAdmin:5.0.2
MySQL:5.7.30
今回作成するファイル
html
- index.php
- index_add_cart.php
- cart.php
- cart_delete.php
- finish.php
model
- carts.php
view
- index_view.php
- cart_view.php
- finish_view.php
テーブルの作成
sample_carts
CREATE TABLE `sample_carts` (
`cart_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`item_id` int(11) NOT NULL,
`amount` int(11) NOT NULL,
`created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `sample_carts`
MODIFY `cart_id` int(11) NOT NULL AUTO_INCREMENT,
ADD PRIMARY KEY (`cart_id`),
ADD KEY `item_id` (`item_id`),
ADD KEY `user_id` (`user_id`);
定義
const.php
define('INDEX_URL', '/index.php');
define('CART_URL', '/cart.php');
define('FINISH_URL', '/finish.php');
Viewの作成
index_view.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta chartset="UTF-8">
<title>商品一覧</title>
</head>
<body>
<h1>商品一覧</h1>
<p>ようこそ、<?php print($user['user_name']); ?>さん。</p>
<a href="<?php print(ADMIN_URL);?>">商品管理</a>
<a href="<?php print(CART_URL);?>">カート</a>
<a href="<?php print(LOGOUT_URL);?>">ログアウト</a>
<!-- メッセージ・エラーメッセージ -->
<?php include VIEW_PATH . 'templates/messages.php'; ?>
<!-- 商品一覧 -->
<?php foreach($items as $item){ ?>
<div>
<?php print($item['name']); ?>
<?php print($item['price']); ?>
<!-- 売り切れの場合は、formを置換 -->
<?php if($item['stock'] > 0){ ?>
<form method="post" action="index_add_cart.php">
<input type="submit" value="カートに追加">
<input type="hidden" name="item_id" value="<?php print($item['item_id']) ?>">
</form>
<?php }else{ ?>
<p>現在、売り切れです。</p>
<?php } ?>
</div>
<?php } ?>
</body>
</html>
cart_view.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>カート</title>
</head>
<body>
<h1>商品一覧</h1>
<p>ようこそ、<?php print($user['user_name']); ?>さん。</p>
<a href="<?php print(ADMIN_URL);?>">商品管理</a>
<a href="<?php print(INDEX_URL);?>">商品一覧</a>
<a href="<?php print(LOGOUT_URL);?>">ログアウト</a>
<!-- メッセージ・エラーメッセージ -->
<?php include VIEW_PATH . 'templates/messages.php'; ?>
<!-- カート一覧 -->
<?php if(count($carts) > 0){ ?>
<table>
<thead>
<tr>
<th>商品名</th>
<th>価格</th>
<th>数量</th>
<th>小計</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach($carts as $cart){ ?>
<tr>
<td><?php print($cart['name']); ?></td>
<td><?php print($cart['price']); ?></td>
<td><?php print($cart['amount']); ?></td>
<td><?php print($cart['price'] * $cart['amount']); ?></td>
<td>
<form method="post" action="cart_delete.php">
<input type="submit" value="削除">
<input type="hidden" name="cart_id" value="<?php print($cart['cart_id']); ?>">
</form>
</td>
</tr>
<?php } ?>
</tbody>
</table>
<p>合計金額:<?php print($total_price); ?></p>
<form method="post" action="finish.php">
<input type="submit" value="購入する">
</form>
<?php }else{ ?>
<p>カートに商品はありません。</p>
<?php } ?>
</body>
</html>
finish_view.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ご購入ありがとうございました!</title>
</head>
<body>
<h1>ご購入ありがとうございました!</h1>
<!-- メッセージ・エラーメッセージ -->
<?php include VIEW_PATH . 'templates/messages.php'; ?>
<!-- 購入した商品 -->
<?php if(count($carts) > 0){ ?>
<table>
<thead>
<tr>
<th>商品名</th>
<th>価格</th>
<th>購入数</th>
<th>小計</th>
</tr>
</thead>
<tbody>
<?php foreach($carts as $cart){ ?>
<tr>
<td><?php print($cart['name']); ?></td>
<td><?php print($cart['price']); ?></td>
<td><?php print($cart['amount']); ?></td>
<td><?php print($cart['price'] * $cart['amount']); ?></td>
</tr>
<?php } ?>
</tbody>
</table>
<p>合計金額:<?php print($total_price); ?></p>
<?php }else{ ?>
<p>カートに商品はありません。</p>
<?php } ?>
</body>
</html>
カートに追加
Model
carts.php
<?php
require_once MODEL_PATH . 'functions.php';
require_once MODEL_PATH . 'db.php';
// カートに追加するために必要なデータ
function get_user_cart($db, $user_id, $item_id){
$sql = "
SELECT
sample_items.item_id,
sample_items.name,
sample_items.price,
sample_items.stock,
sample_carts.cart_id,
sample_carts.user_id,
sample_carts.amount
FROM
sample_carts
JOIN
sample_items
ON
sample_carts.item_id = sample_items.item_id
WHERE
sample_carts.user_id = ?
AND
sample_items.item_id = ?
";
return fetch_query($db, $sql, array($user_id, $item_id));
}
// カートに追加(既に同じ商品があれば、個数のみUpdate)
function add_cart($db, $user_id, $item_id ) {
$cart = get_user_cart($db, $user_id, $item_id);
if($cart === false){
return insert_cart($db, $user_id, $item_id);
}
return update_cart_amount($db, $cart['cart_id'], $cart['amount'] + 1);
}
function insert_cart($db, $user_id, $item_id, $amount = 1){
$sql = "
INSERT INTO
sample_carts(
item_id,
user_id,
amount
)
VALUES(?,?,?)
";
return execute_query($db, $sql, array($item_id, $user_id, $amount));
}
function update_cart_amount($db, $cart_id, $amount){
$sql = "
UPDATE
sample_carts
SET
amount = ?
WHERE
cart_id = ?
LIMIT 1
";
return execute_query($db, $sql, array($amount, $cart_id));
}
Controller
index.php
<?php
require_once '../conf/const.php';
require_once MODEL_PATH. 'functions.php';
require_once MODEL_PATH. 'users.php';
require_once MODEL_PATH. 'items.php';
session_start();
if(is_logined() === false){
redirect_to(LOGIN_URL);
}
$db = get_db_connect();
$user = get_login_user($db);
$items = get_items($db);
include_once VIEW_PATH. 'index_view.php';
index_add_cart.php
<?php
require_once '../conf/const.php';
require_once MODEL_PATH. 'functions.php';
require_once MODEL_PATH. 'users.php';
require_once MODEL_PATH. 'items.php';
require_once MODEL_PATH. 'cart.php';
session_start();
if(is_logined() === false){
redirect_to(LOGIN_URL);
}
$db = get_db_connect();
$user = get_login_user($db);
$item_id = get_post('item_id');
// カートに追加
if(add_cart($db, $user['user_id'], $item_id)){
set_message('カートに商品を追加しました。');
} else{
set_error('カートの更新に失敗しました。');
}
redirect_to(INDEX_URL);
カートの商品を購入
Model
functions.php
function has_error(){
return isset($_SESSION['__errors']) && count($_SESSION['__errors']) !== 0;
}
carts.php
// カートの商品データ
function get_user_carts($db, $user_id){
$sql = "
SELECT
sample_items.item_id,
sample_items.name,
sample_items.price,
sample_items.stock,
sample_carts.cart_id,
sample_carts.user_id,
sample_carts.amount
FROM
sample_carts
JOIN
sample_items
ON
sample_carts.item_id = sample_items.item_id
WHERE
sample_carts.user_id = ?
";
return fetch_all_query($db, $sql, array($user_id));
}
// カートの商品の合計額
function sum_carts($carts){
$total_price = 0;
foreach($carts as $cart){
$total_price += $cart['price'] * $cart['amount'];
}
return $total_price;
}
// 購入処理
function purchase_carts($db, $carts){
if(validate_cart_purchase($carts) === false){
return false;
}
// 購入後、カートの中身削除&在庫変動
$db->beginTransaction();
try {
foreach($carts as $cart){
if(update_stock($db, $cart['item_id'], $cart['stock'] - $cart['amount']) === false){
set_error($cart['name'] . 'の購入に失敗しました。');
}
}
delete_user_carts($db, $carts[0]['user_id']);
$db->commit();
}catch(PDOException $e){
$db->rollback();
throw $e;
}
}
function delete_user_carts($db, $user_id){
$sql = "
DELETE FROM
sample_carts
WHERE
user_id = ?
";
execute_query($db, $sql, array($user_id));
}
// バリデーション
function validate_cart_purchase($carts){
if(count($carts) === 0){
set_error('カートに商品が入っていません。');
return false;
}
foreach($carts as $cart){
if($cart['stock'] - $cart['amount'] < 0){
set_error($cart['name'] . 'は在庫が足りません。購入可能数:' . $cart['stock']);
}
}
if(has_error() === true){
return false;
}
return true;
}
Controller
cart.php
<?php
require_once '../conf/const.php';
require_once MODEL_PATH . 'functions.php';
require_once MODEL_PATH . 'users.php';
require_once MODEL_PATH . 'items.php';
require_once MODEL_PATH . 'carts.php';
session_start();
if(is_logined() === false){
redirect_to(LOGIN_URL);
}
$db = get_db_connect();
$user = get_login_user($db);
$carts = get_user_carts($db, $user['user_id']);
$total_price = sum_carts($carts);
require_once VIEW_PATH. 'cart_view.php';
finish.php
<?php
require_once '../conf/const.php';
require_once MODEL_PATH . 'functions.php';
require_once MODEL_PATH . 'users.php';
require_once MODEL_PATH . 'items.php';
require_once MODEL_PATH . 'carts.php';
session_start();
if(is_logined() === false){
redirect_to(LOGIN_URL);
}
$db = get_db_connect();
$user = get_login_user($db);
$carts = get_user_carts($db, $user['user_id']);
$total_price = sum_carts($carts);
// 購入処理
if(purchase_carts($db, $carts) === false){
set_error('商品が購入できませんでした。');
redirect_to(CART_URL);
}
include_once VIEW_PATH. 'finish_view.php';
カートの商品を削除
Model
carts.php
// カートの商品の削除
function delete_cart($db, $cart_id){
$sql = "
DELETE FROM
sample_carts
WHERE
cart_id = ?
LIMIT 1
";
return execute_query($db, $sql, array($cart_id));
}
Controller
cart_delete.php
<?php
require_once '../conf/const.php';
require_once MODEL_PATH . 'functions.php';
require_once MODEL_PATH . 'users.php';
require_once MODEL_PATH . 'items.php';
require_once MODEL_PATH . 'carts.php';
session_start();
if(is_logined() === false){
redirect_to(LOGIN_URL);
}
$db = get_db_connect();
$user = get_login_user($db);
$cart_id = get_post('cart_id');
if(delete_cart($db, $cart_id)){
set_message('カートの商品を削除しました。');
} else {
set_error('カートの商品の削除に失敗しました。');
}
redirect_to(CART_URL);