20200820のMySQLに関する記事は2件です。

【PHPでECサイト④】購入履歴・購入明細

はじめに

今回は、購入履歴を実装していきます。
※当ページは、【PHPでECサイト】で作られたものを前提にしています。

バージョン

PHP:7.4.5
phpMyAdmin:5.0.2
MySQL:5.7.30

今回作成するファイル

html
- history.php
- detail.php

model
- histories.php

view
- history_view.php
- detail_view.php

テーブルの作成

sample_histories
CREATE TABLE `sample_histories` (
    `order_id` int(11) NOT NULL,
    `user_id` int(11) NOT NULL,
    `created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `sample_histories`
  MODIFY `order_id` int(11) NOT NULL AUTO_INCREMENT,
  ADD PRIMARY KEY (`order_id`),
  ADD KEY `user_id` (`user_id`);
sample_details
CREATE TABLE `sample_details` (
    `order_id` int(11) NOT NULL,
    `item_id` int(11) NOT NULL,
    `amount` int(11) NOT NULL,
    `created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `sample_details`
  ADD KEY `item_id` (`item_id`);

定義

const.php
define('HISTORY_URL', '/order_history.php');
define('DETAIL_URL', 'order_detail.php');

カートの購入処理に追記

carts.php
// 購入処理
function purchase_carts($db, $carts){
  if(validate_cart_purchase($carts) === false){
    return false;
  }
  // 購入後、カートの中身削除&在庫変動&購入履歴・明細にデータを挿入
  $db->beginTransaction();
  try {
    insert_history($db, $carts[0]['user_id']);
    $order_id = $db->lastInsertId();

    foreach($carts as $cart){ 
      insert_detail($db, $order_id, $cart['item_id'], $cart['price'], $cart['amount']);   
      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;
  }
}

// 購入履歴へINSERT
function insert_history($db, $user_id){
  $sql = "
    INSERT INTO
      sample_histories(
        user_id
      )
    VALUES(?)
  ";
  return execute_query($db, $sql, array($user_id));
}

// 購入明細にINSERT
function insert_detail($db, $order_id, $item_id, $price, $amount){
  $sql = "
    INSERT INTO
      sample_details(
        order_id,
        item_id,
        price,
        amount
      )
    VALUES(?,?,?,?)
  ";
  return execute_query($db, $sql, array($order_id, $item_id, $price, $amount));
}

購入履歴

Model

histories.php
<?php
require_once MODEL_PATH. 'functions.php';
require_once MODEL_PATH. 'db.php';

// ユーザ毎の購入履歴
function get_history($db, $user_id){
    $sql = "
      SELECT
        sample_histories.order_id,
        sample_histories.created,
        SUM(sample_details.price * sample_details.amount) AS total
      FROM
        sample_histories
      JOIN
        sample_details
      ON
        sample_histories.order_id = sample_details.order_id
      WHERE
        user_id = ?
      GROUP BY
        order_id
      ORDER BY
        created desc
    ";
    return fetch_all_query($db, $sql, array($user_id));
}

View

history_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(!empty($histories)){ ?>
    <table>
      <thead>
        <tr>
          <th>注文番号</th>
          <th>購入日時</th>
          <th>合計金額</th>
          <th></th>
        </tr>
      </thead>
      <tbody>
      <?php foreach($histories as $history){ ?>
        <tr>
          <td><?php print($history['order_id']); ?></td>
          <td><?php print($history['created']); ?></td>
          <td><?php print($history['total']); ?></td>
          <td>
            <form method="post" action="detail.php">
              <input type="submit" value="購入明細表示">
              <input type="hidden" name="order_id" value="<?php print($history['order_id']); ?>">
            </form>
          </td>
        </tr>
      <?php } ?>
      </tbody>
    </table>
    <?php }else{ ?>
    <p>購入履歴がありません。</p>
    <?php } ?>
  </body>
</html>

Controller

history.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';
require_once MODEL_PATH. 'histories.php';

session_start();

if(is_logined() === false){
  redirect_to(LOGIN_URL);
}

$db = get_db_connect();
$user = get_login_user($db);
$histories = get_history($db, $user['user_id']);

$order_id = get_post('order_id');

include_once VIEW_PATH. 'history_view.php';

購入明細

Model

histories.php
// ユーザ毎の購入明細
function get_detail($db, $order_id){
    $sql = "
      SELECT
        sample_details.price,
        sample_details.amount,
        sample_details.created,
        SUM(sample_details.price * sample_details.amount) AS subtotal,
        sample_items.name
      FROM
        sample_details
      JOIN
        sample_items
      ON
        sample_details.item_id = sample_items.item_id
      WHERE
        order_id = ?
      GROUP BY
        sample_details.price, sample_details.amount, sample_details.created, sample_items.name
    ";
    return fetch_all_query($db, $sql, array($order_id));
}

View

detail_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'; ?>

    <!-- 購入明細 -->
    <table>
      <thead>
        <tr>
          <th>注文番号</th>
          <th>購入日時</th>
          <th>合計金額</th>
        </tr>
      </thead>
      <tbody>
      <?php foreach($histories as $history){ ?>
        <tr>
          <td><?php print($history['order_id']); ?></td>
          <td><?php print($history['created']); ?></td>
          <td><?php print($history['total']); ?></td>
          <td>
            <form method="post" action="detail.php">
              <input type="submit" value="購入明細表示">
              <input type="hidden" name="order_id" value="<?php print($history['order_id']); ?>">
            </form>
          </td>
        </tr>
      <?php } ?>
      </tbody>
    </table>

    <!-- 購入明細 -->
    <table>
      <thead>
        <tr>
          <th>商品名</th>
          <th>価格</th>
          <th>購入数</th>
          <th>小計</th>
        </tr>
      </thead>
      <tbody>
      <?php foreach($details as $detail){ ?>
        <tr>
          <td><?php print($detail['name']); ?></td>
          <td><?php print($detail['price']); ?></td>
          <td><?php print($detail['amount']); ?></td>
          <td><?php print($detail['subtotal']); ?></td>
        </tr>
      <?php } ?>
      </tbody>
    </table>
  </body>
</html>

Controller

detail.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';
require_once MODEL_PATH. 'histories.php';

session_start();

if(is_logined() === false){
  redirect_to(LOGIN_URL);
}

$db = get_db_connect();
$user = get_login_user($db);
$histories = get_history($db, $user['user_id']);

$order_id = get_post('order_id');
$details = get_detail($db, $order_id);

include_once VIEW_PATH. 'detail_view.php';
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Herokuを使って開発アプリを本番環境へデプロイする

開発環境

  • PHP 7.2
  • Laravel 5.6
  • MySQL 5.7
  • Docker
  • Nginx

おさえておきたい料金体系

基本無料。
クレカ登録をすると稼働時間の増加以外にもアドオンの追加が可能になる。

Freeプランではいくつか機能制限があります。

アカウント毎に、アプリケーションは月に550時間までの稼働時間が割り当てられる
アカウントにクレジットカードを紐付けると1000時間に増える
公開しているアプリケーションに30分間アクセスがないと、スリープモードに移行する

有料プランになると上記制限がすべてなくなる($25/月〜)

詳細はこちら

デプロイ方法

イメージ:gitのherokuリポジトリを本番環境へデプロイするだけ

0. Herokuアカウントの登録

(アカウントをもっていればスルーで)
以下ページよりアカウントを作成する
Heroku公式より

1.HerokuCLIをローカル環境にインストールする

Herokuを使うにはHeroku CLIというアプリケーションをローカル環境にインストールする必要がある。
これをインストールすることでgitを使ってデプロイが可能になる。

sudo snap install --classic heroku

※上記コマンドはLinux系のUbuntuコマンドなため各自環境に沿ったコマンドを実施する必要あり詳細は公式で確認

2. Herokuへログイン

ローカル環境で以下コマンドを入力しHerokuへログインする

heroku login -i
Enter your Heroku credentials.
Email: Herokuに登録したメールアドレスを入力
Password: Herokuに登録したパスワードを入力

Logged in as 登録したメールアドレス   //ログイン完了

3.Herokuアプリケーションの作成

デプロイしたいアプリケーションのプロジェクト直下にて下記コマンドを実行。

heroku create アプリケーション名

アプリケーション名がhttps://Herokuアプリケーション名.herokuapp.com/とドメイン名になります

Creating ⬢ example.app.. !
 ▸    Name example.app is already taken

heroku appsコマンドで作成したアプリが確認できれば作成完了

4.リモートリポジトリherokuの確認

念の為git 環境にherokuリモートリポジトリがあるか確認

git remote -v

5.Heroku設定ファイルの新規作成

プロジェクトルート直下に以下コマンドでProcfileを作成する

echo "web: vendor/bin/heroku-php-nginx -C nginx.conf public/" > Procfile

Procfileが以下のようになっているか確認

web: vendor/bin/heroku-php-nginx -C nginx.conf public/

※今回はNginxサーバーですがapacheの場合は

echo "web: vendor/bin/heroku-php-apache2 public/" > Procfile

で作成

Procfileを作業ブランチにコミット&プッシュし、ローカルmasterブランチへマージ

6.本番環境へデプロイする

いよいよデプロイといってもデプロイしたいmasterブランチへ移動して下記のコマンドを実行するだけ

git push heroku master

1分ほど待ち、下記の表記がでればデプロイ完了

remote: Verifying deploy... done.

このままだとURLにアクセスしてもエラーが出るので後ほど環境変数を設定する

URLを叩いて以下のエラーが出たら・・・

  • There's nothing here, yet. ブランチへ入力したURLが間違っている可能性があります。スペルミスを確認しましょう
  • Forbidden Procfileの設定が原因の可能性があります。こちらもスペースやスペルミス、masterブランチにProcfileがあるかを確認しましょう。

7.MySQLの導入

Herokuには複数のadd-onが用意されており、MySQLを使うための ClearDB MySQL をインストールする必要がある。
下記コマンドを実行。

heroku addons:create cleardb:ignite

これでFreeプランのMySQLが追加される。

以下のエラーが出た場合はアカウントにクレジットカードの登録が必要

▸    Please verify your account to install this add-on plan (please enter a credit card) For more
▸    information, see https://devcenter.heroku.com/categories/billing Verify now at
▸    https://heroku.com/verify

あとは環境変数を設定するだけ

環境変数の設定

.envはgitignoreされているためherokuリポジトリには反映されません。
heroku環境に環境変数を直接設定する必要があります。

  • 設定コマンド heroku config:set 環境変数名=キー
  • 確認コマンド heroku config

APP_KEYの設定

DockerPHPコンテナ内プロジェクトルート直下で

$ php artisan key:generate --show

内容をコピーしてローカル環境プロジェクトルート直下で下記コマンドを入力

heroku config:set APP_KEY=base64:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

設定した APP_KEY が設定されていればOK。

MySQLの設定

heroku configで環境変数を確認。
cleardbのadd-onを追加しているためCLEARDB_DATABASE_URL:という環境変数が自動で設定されている。

CLEARDB_DATABASE_URL:  mysql://<ユーザー名>:<パスワード>@<ホスト名>/<データベース名>?reconnect=true

これをもとに各環境変数を設定

$ heroku config:set DB_CONNECTION=mysql
$ heroku config:set DB_DATABASE='<データベース名>'
$ heroku config:set DB_USERNAME='<ユーザー名>'
$ heroku config:set DB_PASSWORD='<パスワード>'
$ heroku config:set DB_HOSTNAME='<ホスト名>'
$ heroku config:set DB_PORT='3306'

その他の環境変数

APP_URL

$ heroku config set:https://アプリケーション名.herokuapp.com

slack認証系

SLACK_KEY=ローカル環境の`.env`の記述と同じ
SLACK_REDIRECT_URI=ローカル環境の`.env`の記述と同じ
SLACK_SECRET=ローカル環境の`.env`の記述と同じ

S3系

AWS_ACCESS_KEY_ID=ローカル環境の`.env`の記述と同じ
AWS_BUCKET=ローカル環境の`.env`の記述と同じ
AWS_DEFAULT_REGION=ローカル環境の`.env`の記述と同じ
AWS_SECRET_ACCESS_KEY=ローカル環境の`.env`の記述と同じ

その他の設定方法

Herokuのビルドに関する設定

buildpackを追加する

  • Herokuダッシュボード内の上部メニューのSettingsを選択

  • Add buildpackの選択

  • node.jsの選択

  • Save changesで完了

  • PHPの選択

  • Save changesで完了

* heroku/nodejs
* heroku/php

が表示されれば、buildpackの追加は完了

データベースのマイグレーション

Herokuからデータベース(MySql)に接続できるよう設定済みですが、まだテーブルを作成していません。
そこで、Laravelのマイグレーションコマンドを使ってテーブルを作成します。
以下コマンドを実行してください。

$ heroku run php artisan migrate —seed

heroku run (実行したいコマンド)で、Heroku上でコマンドを実行できます。
コマンドを実行すると、以下が表示されるので、yesと入力してエンターキーを押してください。

Do you really wish to run this command? (yes/no) [no]:

以下のように各テーブルのマイグレーションが完了した旨のメッセージが表示されれば問題ありません。

Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (0.1 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (0.04 seconds)

Mysql接続コマンド

mysql -h <DB_HOSTNAME> -u <DB_USERNAME> -p -D <DB_DATABASE>

作業内容を本番環境へ反映したいとき

ローカルのmasterブランチに変更内容を反映させgit push heroku masterをするだけ

Heroku環境内に入るコマンド

heroku run bash

共同開発者の追加

  • Heroku にログインし、任意のサービスを選択
  • 上部メニューのaccessを選択
  • Add collaboratorを押下し、共同開発者のアカウントのメールアドレスを入力後、save changeを押下
  • 招待者のメールアドレスが追加されていることを確認
  • 招待者はメールの案内に沿ってHerokuにアクセス

これでデプロイやHeroku環境系の操作が可能になります。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む