音楽イベントのグッズを販売するECサイトを作ってみた

# はじめに
個人開発で「音楽イベントのグッズを販売するECサイト」を作ってたので、紹介します。
![melody-market_top-movie.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/e0189049-0272-49f6-7715-c4ef30dba2d0.gif)

# 概要
音楽のライブイベントに足を運ぶと、Tシャツや帽子、ステッカーなど様々なグッズが販売されています。それらのグッズをオンラインで販売しているECサイトを作成しました。
運用は考えておらず、あくまで自分の練習・スキルアップとして作ったものです。
技術スタックについては後ほど詳細を記載しますが、主にPHP, Laravelを用いており、MPAのWebアプリケーションとなっています。

# URL
## デプロイ先

システムの利用者の種別は、ユーザー（一般の利用者）、オーナー（店舗を運営）、管理者（システムを管理）の3つがあります。

:::note warn
起動に数秒時間がかかります。
:::

ユーザー：https://melody-market.fly.dev &emsp;&emsp;&emsp;&emsp;&emsp;&nbsp; （ゲストログイン機能でログイン可）
オーナー：https://melody-market.fly.dev/owner/login （入力フォームの初期値でログイン可）
管理者&emsp;：https://melody-market.fly.dev/admin/login （入力フォームの初期値でログイン可）

## GitHub

https://github.com/yuuhei-koutoku/laravel-ecsite

# 制作背景
音楽のライブイベントに参加することが、私の趣味の1つだからです。イベント会場ではグッズ販売が行われている場所があり、長蛇の列ができています。混雑していると待ち時間で30分以上かかることもあり、待ち時間なしで購入できるECサイトがあったら便利だと思い、作成しました。

<details><summary>【余談】筆者が好きなアーティストは......</summary>

MY FIRST STORYです。
I'm a messや夢幻（鬼滅の刃 オープニング）が有名ですかね。
![S__66936888.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/b8b49abb-38ef-c79d-504f-215dd6a5817a.jpeg)
個人的にはREVIVERが好きです。
↓テンション上げたい時に聞いてみてください。
[MY FIRST STORY - REVIVER - Official Music Video](https://youtu.be/VvShHLo88_c)
</details>

ただし、初めから音楽イベントグッズのECサイトを作ろうと思っていたわけではないです。最初は何のコンセプトもありませんでした。というのも、このアプリケーションは下記のUdemy教材をベースに作成しているからです。

https://www.udemy.com/course/laravel-multi-ec

このUdemy教材で学習を終えた後、何か自分なりにアレンジ出来ないかと考え、コンセプトやオリジナル機能などを追加しました。かなりざっくりではありますが、Udemyでの実装が5割、オリジナルの実装が5割くらいです。

# 画面イメージ

システムの利用者の種別ごとに記載します。

<details><summary>ユーザー</summary>

### トップページ
商品の一覧を閲覧できます。カテゴリー検索、キーワード検索、CSVダウンロード、並び替え、表示件数切替など、多数の機能を実装しています。
![スクリーンショット 2024-10-03 14.53.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/f821f28a-d7e5-ead7-eeb2-8f5ecce51489.png)

### 商品詳細
商品や店舗の詳細を閲覧できます。認証時は表示されている商品の数量を選択し、その商品をカートに入れることができます。
![スクリーンショット 2024-10-03 14.53.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/9f06df1e-bc40-251c-e939-a090fcd257c0.png)

### カートを表示
認証済みユーザーがカートに入れた商品を閲覧できます。
![スクリーンショット 2024-10-03 14.53.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/cdbdeff0-844e-8800-d583-8f1179d42a6a.png)

### 決済ページ
Stripeの決済ページです。購入手続きが完了すると、ユーザーとオーナーにメールが送信される仕組みです。ただし、StripeとMailtrapはテストモードで実装しているため、実際に請求や決済、メール送信は行われません。
![スクリーンショット 2024-10-03 15.05.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/51dc8bdf-9b52-4e74-c0dd-17194cc81f45.png)

### お問い合わせ
管理者へ問い合わせを送ることができます。
![スクリーンショット 2024-10-03 14.53.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/587334ea-774e-90fe-5a8a-a964f33f7c25.png)

### プロフィール
商品の購入履歴やプロフィール情報更新ができます。
![スクリーンショット 2024-10-03 14.54.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/4c94240e-ee65-c8e2-9f03-ce276920c1c2.png)

</details>

<details><summary>オーナー</summary>

### 店舗情報
店舗の情報を閲覧、編集できます。
![スクリーンショット 2024-10-03 14.54.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/f4a31561-76be-d818-e671-ffeb5db83dbd.png)
![スクリーンショット 2024-10-03 14.58.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/678e0e55-5827-2ae3-e7fb-d9fe5253057b.png)

### 画像管理
商品で使用する画像の作成、編集、削除ができます。
![スクリーンショット 2024-10-03 14.54.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/e18573b7-e25b-f584-df17-29e57118d513.png)
![スクリーンショット 2024-10-03 14.58.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/110c306d-7872-df9d-f106-437ad0753e42.png)

### 商品管理
商品の作成、編集、削除ができます。
![スクリーンショット 2024-10-03 14.54.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/4089aea7-e5a5-c07d-a38a-500250cdb53e.png)
![スクリーンショット 2024-10-03 14.58.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/ec2dc354-d660-da2c-9844-7575fa7465ae.png)

</details>

<details><summary>管理者</summary>

### オーナー管理
オーナーを管理できます。
![スクリーンショット 2024-10-03 14.56.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/c4b7d3cb-c533-e8ec-a5f5-d9f2cc0002cd.png)

### 期限切れオーナー管理
期限切れになったオーナーを管理できます。
![スクリーンショット 2024-10-03 14.56.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/61b2ccb7-941a-c1e4-9635-fa4efa79512b.png)

### お問い合わせ管理
ユーザーから来た問い合わせを管理できます。
![スクリーンショット 2024-10-03 14.57.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/defa7b38-eb1c-d1fa-8dc6-50c1edfc5c01.png)
![スクリーンショット 2024-10-03 14.57.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/b7f336f5-b8be-b14b-beec-628d4ed3bd42.png)

</details>

# 技術スタック、開発環境

-   フロントエンド
    -   HTML
    -   CSS
        -   Tailwind CSS 3.1.0
-   バックエンド
    -   PHP 8.2.0
        -   Laravel 9.52.5
-   その他
    -   MAMP
        -   MySQL 5.7.39
        -   Apache
    -   Visual Studio Code
    -   Git / GitHub / SourceTree（バージョン管理）
    -   GitHub Actions（Laravel Pintの実行を自動化）
    -   Stripe（決済機能）
    -   Mailtrap（メール送信機能）
    -   AWS S3（画像保存）
    -   Fly.io（デプロイ `main`ブランチプッシュ時に自動デプロイ）

# 機能

画面イメージと同様、システムの利用者の種別ごとに記載します。

## ユーザー

-   アカウント新規作成、ログイン、ログアウト
-   商品一覧
    -   商品画像、カテゴリー、商品名、単価を表示
    -   カテゴリ検索
    -   キーワード検索
    -   CSVダウンロード（全てのページ または 現在のページのみ）
    -   並び替え（おすすめ順、料金が高い順、料金が安い順、新しい順、古い順）
    -   ページネーション（表示件数切り替え（20 件、50 件、100 件））
-   商品詳細
    -   商品画像切り替え（Swiper.js）
    -   詳細情報表示（カテゴリ、商品名、商品の説明、単価）
    -   カートに入れる
    -   ショップの詳細を表示（Micromodal.js）
-   カートを表示
    -   カートに入れた商品を表示（商品画像、商品名、数量、小計、合計金額）
    -   カートに入れた商品を削除
    -   カートに入れた商品の合計金額を表示
-   購入（Stripe）
    -   カートに入れた商品を表示（商品名、数量、単価、小計、合計金額）
    -   支払いに必要な情報を入力（メールアドレス、カード情報、カード所有者名、国または地域）
    -   購入確定後、ユーザーとオーナーにメール送信を行う（Mailtrap）
-   お問い合わせ
    -   運営へ問い合わせ内容を送信
    -   メッセージの送信を取り消し（論理削除）
-   プロフィール
    -   購入履歴を表示
    -   プロフィール情報（名前、メールアドレス）を更新
    -   パスワード更新
    -   アカウント退会

:::note info
ユーザーのみレスポンシブデザインにしています。
:::

## オーナー

-   ログイン、ログアウト
-   店舗情報
    -   店名及び店舗画像を表示
    -   詳細
        -   更新（店名、店舗情報、店舗画像をS3へアップロード、販売中 or 停止中）
-   画像管理
    -   商品画像一覧
    -   新規登録（商品画像をS3へアップロード）
    -   詳細
        -   商品画像タイトル更新
        -   商品画像削除
-   商品管理
    -   商品一覧
    -   新規登録（商品名、商品情報、価格、表示順、初期在庫、販売する店舗、カテゴリー、複数画像アップロード、販売中 or 停止中）
    -   詳細
        -   更新（商品名、商品情報、価格、表示順、初期在庫、販売する店舗、カテゴリー、複数画像アップロード、販売中 or 停止中）
        -   商品削除

## 管理者

-   ログイン、ログアウト
-   オーナー管理
    -   オーナー管理
        -   名前、メールアドレス、作成日を表示
        -   ページネーション
    -   新規登録（オーナー名、メールアドレス、パスワード、パスワード確認）
    -   更新（オーナー名、メールアドレス、店名、パスワード、パスワード確認）
    -   削除（論理削除）
-   期限切れオーナー管理
    -   期限切れオーナー管理
        -   名前、メールアドレス、期限が切れた日を表示
    -   完全に削除（物理削除）
-   お問い合わせ管理
    -   お問い合わせ管理
        -   問い合わせが送られたユーザーの一覧を表示
    -   お問い合わせ詳細
        -   利用者へお問い合わせの返答を送信
        -   メッセージの送信を取り消し（論理削除）

# ER図

![ER-diagram-laravel_ecsite.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/beb58659-36f5-07c6-bb61-3da2c675ebe0.png)

# 苦労した点

## Laravel Pintの実行をGitHub Actionsで自動化
Laravel Pint（コードスタイル自動整形ツール）をGitHub Actionsで自動実行する仕組みを導入しました。GitHub Actionsを初めて触ったため、当初はかなり苦戦しました。インターネット上の記事やChatGPT、公式リファレンスなどを参照しつつ、トライアンドエラーを繰り返し、最終的に自動化に成功しました。
導入前は、毎回プッシュ前に`./vendor/bin/pint`コマンドを手動で実行していましたが、自動化することで手動実行が不要になり、作業が大幅に効率化されました。費用対効果は大きいので、導入して正解だったと感じています。詳しくは下記の記事をご覧ください。

https://qiita.com/Yuhei_K/items/685f1d832c4b4f30e36c

## 機能追加に伴うデグレを発生させない
スキルアップを目的に多数の機能を実装していたため、後半での追加機能実装時にはデグレが発生しやすく、既存のテーブル定義では対応できない状況が生じました。
既存のコードやテーブル構造を踏まえ、デグレを防ぎつつ新機能を追加する方法を考えながら取り組んだ結果、期待通りに機能を追加することができました。
（ただし、最初に精度の高い設計を行なっていれば、こうした問題は防げたはずなので、反省しています......）

# さいごに
自分にとってはクオリティーの高いアプリを作ることができたので、満足しています。
既存機能を改善したり、機能の追加を行うことは可能ではありますが、区切りの良いところまで進めることができたので、今のところ追加開発は行わない予定です。
たくさん機能を実装したり、今まで触ったことのないツールを使ってみることができたので、良い経験になりました。
個人開発（ポートフォリオ作成）をしている方の参考になれば幸いです。

最後まで読んでいただき、ありがとうございました！