LoginSignup
6
12

More than 3 years have passed since last update.

【PHPでECサイト③】カート機能

Last updated at Posted at 2020-08-17

はじめに

今回は、カート機能を実装していきます。
※当ページは、【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);
6
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
12