161 lines
7.2 KiB
Markdown
161 lines
7.2 KiB
Markdown
# PHP・DB連携 総合演習課題
|
||
|
||
## はじめに(演習の⽬的と取り組み⽅)
|
||
当演習は、講義で学んだことを⾃⼒で実践できるようになるために実施します。 そのために以下の内容を守って演習に取り組んでください。
|
||
|
||
### 納品物、納期を守りましょう
|
||
この演習は、実際の仕事を想定した内容です。
|
||
提出物の内容と提出期限は必ず守ってください。
|
||
作業が間に合わない、提出物に問題が出そうな場合は、**必ずルールにしたがって適切な相⼿に相談してください**。
|
||
|
||
### 適切な⼿順で開発しましょう
|
||
プログラムを書き始める前に、**README.md** や**仕様書**(配布されている場合) を必ず読んでください。
|
||
「**何を作るのか**」、「**どこまで作ればよいのか**」を理解してから作業を始めてください。
|
||
|
||
### 知らないことは⾃分で調べましょう
|
||
この演習には、**講義で扱っていない内容が⼀部含まれています**。
|
||
その場合は、インターネットなどで⾃分で調べながら進めてください。
|
||
調べることも、エンジニアにとって⼤切なスキルの⼀つです。
|
||
|
||
|
||
## 演習目的
|
||
|
||
この演習では、PHPの基礎知識とオブジェクト指向プログラミング(OOP)、そしてMySQLデータベースとの連携を総合的に学習します。
|
||
|
||
### 学習ポイント
|
||
- **クラスとインスタンス**: オブジェクト指向の基本概念を実装する
|
||
- **カプセル化**: データの隠蔽とアクセス制御を実践する
|
||
- **インタフェース**: 契約に基づいた設計を理解する
|
||
- **多態性(ポリモーフィズム)**: インタフェースを通じた柔軟な実装
|
||
- **例外処理**: エラーハンドリングの適切な実装
|
||
- **CRUD操作**: データベースの基本操作(Create, Read, Update, Delete)
|
||
- **JOIN操作**: 複数テーブルを結合したデータ取得
|
||
|
||
## フォルダ構成
|
||
|
||
```
|
||
PHP-EM-OOP-DB/
|
||
│
|
||
├── README.md # このファイル
|
||
├── start-DDL.sql # データベース・テーブル作成SQL
|
||
├── start-DML.sql # 初期データ投入SQL
|
||
│
|
||
├── config/
|
||
│ └── db_config.php # データベース接続設定
|
||
│
|
||
├── interfaces/
|
||
│ └── DataAccessInterface.php # データアクセスインタフェース定義
|
||
│
|
||
├── database/
|
||
│ ├── abstracts/
|
||
│ │ └── BaseAccess.php # データベース接続基底クラス
|
||
│ └── products/
|
||
│ └── ProductAccess.php # 商品データアクセスクラス
|
||
│
|
||
└── public/
|
||
├── index.php # トップページ
|
||
├── product_list.php # 商品一覧表示(実装済み)
|
||
├── product_register.php # 商品登録処理
|
||
├── product_update.php # 商品更新処理
|
||
├── product_delete.php # 商品削除処理
|
||
└── product_join.php # JOIN を使った高度な検索(追加課題)
|
||
```
|
||
|
||
## 課題内容
|
||
|
||
### 前提条件
|
||
|
||
- データベース名: `em_oop_db`
|
||
- ユーザー: `rezouser`
|
||
- パスワード: `Rezo_0000`
|
||
- テーブル: `categories`(カテゴリ)と `products`(商品)の1対多の関係
|
||
|
||
### 【基本課題】CRUD処理の実装
|
||
|
||
#### 1. データベースの準備
|
||
1. A5:SQL MK-2 を開く
|
||
2. データベースの追加と削除を開く
|
||
3. 追加 > MySQL / MariaDB(直接接続)を選択
|
||
4. 以下で入力してください
|
||
|
||
```
|
||
ホスト名:localhost
|
||
ユーザーID:root
|
||
パスワード:Rezo_0000
|
||
データベース:mysql
|
||
```
|
||
5. テスト接続でOKと出ればOK
|
||
6. 「データベースを選択してください」 >> localhost/mysql を選択
|
||
7. `start-DDL.sql` を実行してデータベースとテーブルを作成
|
||
8. データベースの追加と削除を開く
|
||
9. 追加 > MySQL / MariaDB(直接接続)を選択
|
||
10. 以下で入力してください
|
||
|
||
```
|
||
ホスト名:localhost
|
||
ユーザーID:rezouser
|
||
パスワード:Rezo_0000
|
||
データベース:em_oop_db
|
||
```
|
||
11. 「データベースを選択してください」 >> localhost/em_oop_db を選択
|
||
12. `start-DML.sql` を実行して初期データを投入
|
||
|
||
#### 2. 段階的な実装ステップ
|
||
|
||
以下の順番で実装を進めてください。各PHPファイルには `TODO` コメントが記載されています。
|
||
|
||
##### 1段階目: PDOを利用したDB接続処理を実装する
|
||
- `database/abstracts/BaseAccess.php` のコンストラクタ内でPDO接続を実装してください
|
||
- 接続情報:
|
||
- ユーザー: `rezouser`
|
||
- パスワード: `Rezo_0000`
|
||
- データベース名: `em_oop_db`
|
||
|
||
##### 2段階目: 新しい商品を登録する
|
||
- **Create(作成)**: `public/product_register.php` - 新しい商品を登録する
|
||
- `database/products/ProductAccess.php` の `create()` メソッドを実装してください
|
||
|
||
##### 3段階目: 既存の商品情報を更新する
|
||
- **Update(更新)**: `public/product_update.php` - 既存の商品情報を更新する
|
||
- `database/products/ProductAccess.php` の `update()` メソッドを実装してください
|
||
|
||
##### 4段階目: 商品を削除する
|
||
- **Delete(削除)**: `public/product_delete.php` - 商品を削除する
|
||
- `database/products/ProductAccess.php` の `delete()` メソッドを実装してください
|
||
|
||
|
||
|
||
### 【追加課題】JOIN を使った検索機能
|
||
|
||
`public/product_join.php` を実装してください。
|
||
|
||
この課題では、1対多の関係にある複数テーブルを結合して、より高度なデータ取得を行います。
|
||
|
||
#### 実装内容
|
||
|
||
##### 1. 商品一覧(カテゴリ情報付き)の表示
|
||
- **INNER JOIN** を使用して、`products`テーブルと`categories`テーブルを結合
|
||
- 取得するカラム:
|
||
- 商品の全情報(`products.*`)
|
||
- カテゴリ名(`categories.name AS category_name`)
|
||
- カテゴリ説明(`categories.description AS category_description`)
|
||
- 結合条件: `products.category_id = categories.id`
|
||
- 結果を`$productsWithCategory`配列に格納して表示
|
||
- (参考画像 > カテゴリ情報付き商品一覧.png 参照)
|
||
|
||
##### 2. カテゴリ別統計情報の集計
|
||
- **LEFT JOIN** を使用して、全カテゴリの統計を取得(商品がないカテゴリも表示)
|
||
- 取得する情報:
|
||
- カテゴリID(`categories.id`)
|
||
- カテゴリ名(`categories.name`)
|
||
- 商品数(`COUNT(products.id) AS product_count`)
|
||
- 平均価格(`AVG(products.price) AS avg_price`)
|
||
- `GROUP BY categories.id, categories.name` でカテゴリごとにグループ化
|
||
- 結果を`$categoryStats`配列に格納してカード形式で表示
|
||
- (参考画像 > カテゴリ別統計情報.png 参照)
|
||
|
||
#### 学習のポイント
|
||
- **INNER JOIN**: 両方のテーブルに存在するデータのみを取得
|
||
- **LEFT JOIN**: 左側のテーブル(categories)の全レコードを取得し、右側のテーブル(products)にデータがない場合はNULLを返す
|
||
- **集計関数**: `COUNT()`で件数、`AVG()`で平均を計算
|
||
- **GROUP BY**: データをグループ化して集計 |