no message
This commit is contained in:
348
public/product_join.php
Normal file
348
public/product_join.php
Normal file
@@ -0,0 +1,348 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../database/products/ProductAccess.php';
|
||||
|
||||
/**
|
||||
* JOIN を使った高度な検索(追加課題)
|
||||
*
|
||||
* このファイルでは、categoriesテーブルとproductsテーブルを結合して、
|
||||
* カテゴリ情報と共に商品情報を取得します。
|
||||
* また、カテゴリ別の商品数を集計する機能も実装します。
|
||||
*/
|
||||
|
||||
// エラー表示設定(開発時のみ)
|
||||
ini_set('display_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
$message = '';
|
||||
$messageType = '';
|
||||
$productsWithCategory = [];
|
||||
$categoryStats = [];
|
||||
|
||||
try {
|
||||
// ProductAccessを使ってPDO接続を取得
|
||||
$productAccess = new ProductAccess();
|
||||
$pdo = $productAccess->getConnection();
|
||||
|
||||
// TODO: INNER JOINを使って、商品情報とカテゴリ情報を結合して取得してください
|
||||
$sql = ""; // ここにJOINを使ったSQL文を記述
|
||||
|
||||
// TODO: ここでSQLを実行して結果を$productsWithCategoryに格納
|
||||
|
||||
|
||||
// TODO: カテゴリ別の商品数と平均価格を集計してください
|
||||
$statsSql = ""; // ここに集計用のSQL文を記述
|
||||
|
||||
// TODO: ここでSQLを実行して結果を$categoryStatsに格納
|
||||
} catch (Exception $e) {
|
||||
$message = "データの取得に失敗しました: " . $e->getMessage();
|
||||
$messageType = "error";
|
||||
}
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="ja">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>JOIN検索 - 追加課題</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
|
||||
min-height: 100vh;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
background: white;
|
||||
padding: 30px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #333;
|
||||
margin-bottom: 10px;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #555;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 15px;
|
||||
font-size: 22px;
|
||||
border-bottom: 2px solid #11998e;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
color: #666;
|
||||
margin-bottom: 25px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 25px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
padding: 8px 16px;
|
||||
background: #11998e;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 5px;
|
||||
font-size: 14px;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.nav-links a:hover {
|
||||
background: #0e7d72;
|
||||
}
|
||||
|
||||
.message {
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.message.error {
|
||||
background: #f8d7da;
|
||||
color: #721c24;
|
||||
border: 1px solid #f5c6cb;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
padding: 12px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
th {
|
||||
background: #11998e;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
tr:hover {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.price {
|
||||
text-align: right;
|
||||
font-weight: bold;
|
||||
color: #e74c3c;
|
||||
}
|
||||
|
||||
.stock {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.category-badge {
|
||||
display: inline-block;
|
||||
padding: 4px 12px;
|
||||
background: #11998e;
|
||||
color: white;
|
||||
border-radius: 15px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.stat-card h3 {
|
||||
margin-bottom: 15px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.stat-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.stat-row:last-child {
|
||||
border-bottom: none;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 14px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.no-data {
|
||||
text-align: center;
|
||||
padding: 40px;
|
||||
color: #999;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
background: #e7f3ff;
|
||||
border-left: 4px solid #2196F3;
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.info-box h3 {
|
||||
color: #1976D2;
|
||||
margin-bottom: 10px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.info-box p {
|
||||
color: #555;
|
||||
line-height: 1.6;
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>🔗 JOIN を使った高度な検索</h1>
|
||||
<p class="subtitle">Advanced - 複数テーブルを結合してデータを取得します</p>
|
||||
|
||||
<div class="nav-links">
|
||||
<a href="index.php">🏠 トップ</a>
|
||||
<a href="product_list.php">📋 一覧表示</a>
|
||||
<a href="product_register.php">📝 新規登録</a>
|
||||
<a href="product_update.php">✏️ 更新</a>
|
||||
<a href="product_delete.php">🗑️ 削除</a>
|
||||
</div>
|
||||
|
||||
<div class="info-box">
|
||||
<h3>📚 追加課題のポイント</h3>
|
||||
<p>
|
||||
この課題では、<strong>INNER JOIN</strong> と <strong>LEFT JOIN</strong> を使用します。<br>
|
||||
・INNER JOIN: カテゴリと商品の両方に存在するデータのみを取得<br>
|
||||
・LEFT JOIN: 全カテゴリを取得し、商品がない場合も表示<br>
|
||||
・集計関数: COUNT()で商品数、AVG()で平均価格を計算<br>
|
||||
・GROUP BY: カテゴリごとにグループ化
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php if ($message): ?>
|
||||
<div class="message <?php echo $messageType; ?>">
|
||||
<?php echo htmlspecialchars($message); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- カテゴリ別統計情報 -->
|
||||
<h2>📊 カテゴリ別統計情報</h2>
|
||||
<?php if (empty($categoryStats)): ?>
|
||||
<div class="no-data">
|
||||
統計情報を表示できません。<br>
|
||||
TODOを実装してください。
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="stats-grid">
|
||||
<?php foreach ($categoryStats as $stat): ?>
|
||||
<div class="stat-card">
|
||||
<h3><?php echo htmlspecialchars($stat['name']); ?></h3>
|
||||
<div class="stat-row">
|
||||
<span class="stat-label">商品数:</span>
|
||||
<span class="stat-value"><?php echo $stat['product_count']; ?> 件</span>
|
||||
</div>
|
||||
<div class="stat-row">
|
||||
<span class="stat-label">平均価格:</span>
|
||||
<span class="stat-value">
|
||||
<?php
|
||||
echo $stat['avg_price']
|
||||
? '¥' . number_format($stat['avg_price'], 0)
|
||||
: '商品なし';
|
||||
?>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- 商品一覧(カテゴリ情報付き) -->
|
||||
<h2>📦 商品一覧(カテゴリ情報付き)</h2>
|
||||
<?php if (empty($productsWithCategory)): ?>
|
||||
<div class="no-data">
|
||||
商品情報を表示できません。<br>
|
||||
TODOを実装してください。
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>カテゴリ</th>
|
||||
<th>商品名</th>
|
||||
<th>カテゴリ説明</th>
|
||||
<th>価格</th>
|
||||
<th>在庫</th>
|
||||
<th>登録日時</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($productsWithCategory as $product): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($product['id']); ?></td>
|
||||
<td>
|
||||
<span class="category-badge">
|
||||
<?php echo htmlspecialchars($product['category_name']); ?>
|
||||
</span>
|
||||
</td>
|
||||
<td><?php echo htmlspecialchars($product['name']); ?></td>
|
||||
<td><?php echo htmlspecialchars($product['category_description'] ?? '-'); ?></td>
|
||||
<td class="price">¥<?php echo number_format($product['price']); ?></td>
|
||||
<td class="stock"><?php echo htmlspecialchars($product['stock']); ?></td>
|
||||
<td><?php echo htmlspecialchars($product['created_at']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<p style="margin-top: 15px; color: #666; font-size: 14px;">
|
||||
全 <?php echo count($productsWithCategory); ?> 件の商品が表示されています。
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user