功能特点
- 产品展示: 以卡片形式在首页展示所有产品。
- 产品详情: 点击产品可查看大图、详细描述和价格。
- 后台管理: 一个简单的管理界面,可以添加、编辑和删除产品。
- 文件上传: 支持上传产品图片。
- 响应式设计: 适配桌面和移动设备。
第一步:数据库设计
您需要创建一个MySQL数据库和一张表来存储产品信息。

- 创建数据库(例如命名为
product_showcase)。 - 执行以下SQL语句创建
products表:
CREATE TABLE `products` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `description` text NOT NULL, `price` decimal(10,2) NOT NULL, `image_url` varchar(255) NOT NULL, `created_at` timestamp NOT NULL DEFAULT current_timestamp(), `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
第二步:项目文件结构
为了保持代码整洁,我们按照以下结构组织文件:
/product-showcase/
├── admin/ # 后台管理页面
│ ├── add_product.php # 添加产品页面
│ ├── edit_product.php # 编辑产品页面
│ ├── index.php # 后台产品列表
│ └── login.php # 管理员登录页
├── assets/ # 静态资源
│ ├── css/
│ │ └── style.css # 主样式文件
│ └── images/ # 存放上传的产品图片
├── config.php # 数据库连接配置
├── functions.php # 公共函数库
├── header.php # 页面头部
├── footer.php # 页面底部
├── index.php # 网站首页(产品列表)
├── product.php # 产品详情页
└── process.php # 处理表单提交(添加/编辑/删除)
第三步:编写源码文件
我们逐一创建上述文件中的代码。
config.php - 数据库配置
<?php
// 数据库连接配置
define('DB_HOST', 'localhost');
define('DB_USER', 'root'); // 您的数据库用户名
define('DB_PASS', ''); // 您的数据库密码
define('DB_NAME', 'product_showcase'); // 您的数据库名
// 创建数据库连接
$conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
// 检查连接是否成功
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}
// 设置字符集
$conn->set_charset("utf8mb4");
?>
functions.php - 公共函数
<?php
// 获取所有产品
function getProducts($conn) {
$sql = "SELECT * FROM products ORDER BY created_at DESC";
$result = $conn->query($sql);
return $result->fetch_all(MYSQLI_ASSOC);
}
// 根据ID获取单个产品
function getProductById($conn, $id) {
$stmt = $conn->prepare("SELECT * FROM products WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
$result = $stmt->get_result();
return $result->fetch_assoc();
}
// 删除产品
function deleteProduct($conn, $id) {
// 先获取产品图片路径,以便删除文件
$product = getProductById($conn, $id);
if ($product && file_exists('../assets/images/' . $product['image_url'])) {
unlink('../assets/images/' . $product['image_url']);
}
$stmt = $conn->prepare("DELETE FROM products WHERE id = ?");
$stmt->bind_param("i", $id);
return $stmt->execute();
}
// 简单的登录检查(实际项目中应使用更安全的方式,如Session)
function isLoggedIn() {
// 这里为了演示,我们用一个固定的用户名和密码
// 在真实项目中,你应该使用 $_SESSION
if (isset($_POST['username']) && $_POST['username'] === 'admin' && isset($_POST['password']) && $_POST['password'] === 'password123') {
return true;
}
return false;
}
?>
header.php - 页面头部
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">产品展示网站</title>
<link rel="stylesheet" href="assets/css/style.css">
<!-- 引入 Bootstrap CSS 用于快速布局和样式 -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="index.php">我的产品</a>
<div class="navbar-nav ms-auto">
<!-- 如果未登录,显示登录链接 -->
<?php if (!isset($_SESSION['admin_logged_in'])): ?>
<a class="nav-link" href="admin/login.php">登录管理</a>
<?php else: ?>
<!-- 如果已登录,显示退出链接 -->
<a class="nav-link" href="admin/logout.php">退出</a>
<?php endif; ?>
</div>
</div>
</nav>
<div class="container mt-4">
footer.php - 页面底部
</div> <!-- /container -->
<footer class="bg-dark text-white text-center py-3 mt-5">
<p>© <?php echo date("Y"); ?> 产品展示网站. All rights reserved.</p>
</footer>
<!-- 引入 Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
assets/css/style.css - 自定义样式
/* 自定义一些样式 */
.product-card {
transition: transform 0.3s ease;
height: 100%;
}
.product-card:hover {
transform: translateY(-5px);
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
}
.product-card img {
height: 200px;
object-fit: cover;
}
.navbar-brand {
font-weight: bold;
}
index.php - 首页(产品列表)
<?php
require_once 'config.php';
require_once 'functions.php';
require_once 'header.php';
$products = getProducts($conn);
?>
<h1 class="mb-4">我们的产品</h1>
<div class="row">
<?php if (!empty($products)): ?>
<?php foreach ($products as $product): ?>
<div class="col-md-4 mb-4">
<div class="card product-card">
<img src="assets/images/<?php echo htmlspecialchars($product['image_url']); ?>" class="card-img-top" alt="<?php echo htmlspecialchars($product['name']); ?>">
<div class="card-body">
<h5 class="card-title"><?php echo htmlspecialchars($product['name']); ?></h5>
<p class="card-text text-muted">¥ <?php echo htmlspecialchars($product['price']); ?></p>
<a href="product.php?id=<?php echo $product['id']; ?>" class="btn btn-primary">查看详情</a>
</div>
</div>
</div>
<?php endforeach; ?>
<?php else: ?>
<div class="col-12">
<div class="alert alert-info">
暂无产品。
</div>
</div>
<?php endif; ?>
</div>
<?php require_once 'footer.php'; ?>
product.php - 产品详情页
<?php
require_once 'config.php';
require_once 'functions.php';
require_once 'header.php';
if (!isset($_GET['id']) || empty($_GET['id'])) {
echo "<div class='alert alert-danger'>未指定产品ID。</div>";
require_once 'footer.php';
exit();
}
$id = (int)$_GET['id'];
$product = getProductById($conn, $id);
if (!$product) {
echo "<div class='alert alert-danger'>产品未找到。</div>";
require_once 'footer.php';
exit();
}
?>
<div class="row">
<div class="col-md-6">
<img src="assets/images/<?php echo htmlspecialchars($product['image_url']); ?>" class="img-fluid rounded" alt="<?php echo htmlspecialchars($product['name']); ?>">
</div>
<div class="col-md-6">
<h2><?php echo htmlspecialchars($product['name']); ?></h2>
<p class="fs-4 text-primary">¥ <?php echo htmlspecialchars($product['price']); ?></p>
<hr>
<h5>产品描述</h5>
<p><?php echo nl2br(htmlspecialchars($product['description'])); ?></p>
<a href="index.php" class="btn btn-secondary">← 返回列表</a>
</div>
</div>
<?php require_once 'footer.php'; ?>
第四步:后台管理功能
admin/login.php - 管理员登录
<?php session_start(); ?>
<?php require_once '../config.php'; ?>
<?php require_once '../header.php'; ?>
<div class="row justify-content-center mt-5">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h4>管理员登录</h4>
</div>
<div class="card-body">
<?php if (isset($_GET['error'])): ?>
<div class="alert alert-danger">用户名或密码错误。</div>
<?php endif; ?>
<form action="login_process.php" method="POST">
<div class="mb-3">
<label for="username" class="form-label">用户名</label>
<input type="text" class="form-control" id="username" name="username" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">密码</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<button type="submit" class="btn btn-primary w-100">登录</button>
</form>
</div>
</div>
</div>
</div>
<?php require_once '../footer.php'; ?>
admin/login_process.php - 处理登录
<?php
session_start();
require_once '../config.php';
require_once '../functions.php';
if (isLoggedIn()) {
$_SESSION['admin_logged_in'] = true;
header('Location: index.php');
exit;
} else {
header('Location: login.php?error=1');
exit;
}
?>
admin/index.php - 后台产品列表
<?php
session_start();
if (!isset($_SESSION['admin_logged_in'])) {
header('Location: login.php');
exit;
}
require_once '../config.php';
require_once '../functions.php';
require_once '../header.php';
$products = getProducts($conn);
?>
<h1 class="mb-4">产品管理</h1>
<a href="add_product.php" class="btn btn-success mb-3">添加新产品</a>
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>ID</th>
<th>图片</th>
<th>名称</th>
<th>价格</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach ($products as $product): ?>
<tr>
<td><?php echo $product['id']; ?></td>
<td><img src="../assets/images/<?php echo htmlspecialchars($product['image_url']); ?>" alt="<?php echo htmlspecialchars($product['name']); ?>" width="50"></td>
<td><?php echo htmlspecialchars($product['name']); ?></td>
<td>¥ <?php echo htmlspecialchars($product['price']); ?></td>
<td>
<a href="edit_product.php?id=<?php echo $product['id']; ?>" class="btn btn-sm btn-warning">编辑</a>
<a href="../process.php?action=delete&id=<?php echo $product['id']; ?>" class="btn btn-sm btn-danger" onclick="return confirm('确定要删除这个产品吗?');">删除</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php require_once '../footer.php'; ?>
admin/add_product.php - 添加产品页面
<?php
session_start();
if (!isset($_SESSION['admin_logged_in'])) {
header('Location: login.php');
exit;
}
require_once '../config.php';
require_once '../header.php';
?>
<h1 class="mb-4">添加新产品</h1>
<form action="../process.php" method="POST" enctype="multipart/form-data">
<div class="mb-3">
<label for="name" class="form-label">产品名称</label>
<input type="text" class="form-control" id="name" name="name" required>
</div>
<div class="mb-3">
<label for="description" class="form-label">产品描述</label>
<textarea class="form-control" id="description" name="description" rows="4" required></textarea>
</div>
<div class="mb-3">
<label for="price" class="form-label">价格</label>
<input type="number" class="form-control" id="price" name="price" step="0.01" required>
</div>
<div class="mb-3">
<label for="image" class="form-label">产品图片</label>
<input type="file" class="form-control" id="image" name="image" accept="image/*" required>
</div>
<input type="hidden" name="action" value="add">
<button type="submit" class="btn btn-primary">添加产品</button>
<a href="index.php" class="btn btn-secondary">取消</a>
</form>
<?php require_once '../footer.php'; ?>
admin/edit_product.php - 编辑产品页面
<?php
session_start();
if (!isset($_SESSION['admin_logged_in'])) {
header('Location: login.php');
exit;
}
require_once '../config.php';
require_once '../functions.php';
require_once '../header.php';
if (!isset($_GET['id']) || empty($_GET['id'])) {
echo "<div class='alert alert-danger'>未指定产品ID。</div>";
require_once '../footer.php';
exit;
}
$id = (int)$_GET['id'];
$product = getProductById($conn, $id);
if (!$product) {
echo "<div class='alert alert-danger'>产品未找到。</div>";
require_once '../footer.php';
exit;
}
?>
<h1 class="mb-4">编辑产品</h1>
<form action="../process.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="action" value="edit">
<input type="hidden" name="id" value="<?php echo $product['id']; ?>">
<div class="mb-3">
<label for="name" class="form-label">产品名称</label>
<input type="text" class="form-control" id="name" name="name" value="<?php echo htmlspecialchars($product['name']); ?>" required>
</div>
<div class="mb-3">
<label for="description" class="form-label">产品描述</label>
<textarea class="form-control" id="description" name="description" rows="4" required><?php echo htmlspecialchars($product['description']); ?></textarea>
</div>
<div class="mb-3">
<label for="price" class="form-label">价格</label>
<input type="number" class="form-control" id="price" name="price" step="0.01" value="<?php echo htmlspecialchars($product['price']); ?>" required>
</div>
<div class="mb-3">
<label for="image" class="form-label">更换产品图片 (留空则不更换)</label>
<input type="file" class="form-control" id="image" name="image" accept="image/*">
<p class="form-text">当前图片: <img src="../assets/images/<?php echo htmlspecialchars($product['image_url']); ?>" alt="Current" width="50"></p>
</div>
<button type="submit" class="btn btn-primary">更新产品</button>
<a href="index.php" class="btn btn-secondary">取消</a>
</form>
<?php require_once '../footer.php'; ?>
第五步:核心处理逻辑 process.php
这个文件是整个网站的“大脑”,负责处理所有来自表单的请求。
<?php
require_once 'config.php';
require_once 'functions.php';
// 检查请求方法
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// 1. 添加产品
if (isset($_POST['action']) && $_POST['action'] === 'add') {
$name = $_POST['name'];
$description = $_POST['description'];
$price = $_POST['price'];
// 处理图片上传
$target_dir = "assets/images/";
$target_file = $target_dir . basename($_FILES["image"]["name"]);
$imageFileType = strtolower(pathinfo($target_file, PATHINFO_EXTENSION));
// 检查文件是否为真实图片
$check = getimagesize($_FILES["image"]["tmp_name"]);
if($check !== false) {
if (move_uploaded_file($_FILES["image"]["tmp_name"], $target_file)) {
$image_url = $_FILES["image"]["name"];
// 插入数据库
$stmt = $conn->prepare("INSERT INTO products (name, description, price, image_url) VALUES (?, ?, ?, ?)");
$stmt->bind_param("ssds", $name, $description, $price, $image_url);
if ($stmt->execute()) {
header("Location: index.php");
exit;
} else {
echo "Error: " . $stmt->error;
}
$stmt->close();
} else {
echo "抱歉,上传文件时出错。";
}
} else {
echo "文件不是图片。";
}
}
// 2. 编辑产品
elseif (isset($_POST['action']) && $_POST['action'] === 'edit') {
$id = $_POST['id'];
$name = $_POST['name'];
$description = $_POST['description'];
$price = $_POST['price'];
$image_url_to_update = null;
// 检查是否有新图片上传
if (!empty($_FILES["image"]["name"])) {
$target_dir = "assets/images/";
$target_file = $target_dir . basename($_FILES["image"]["name"]);
$imageFileType = strtolower(pathinfo($target_file, PATHINFO_EXTENSION));
$check = getimagesize($_FILES["image"]["tmp_name"]);
if($check !== false) {
if (move_uploaded_file($_FILES["image"]["tmp_name"], $target_file)) {
$image_url_to_update = $_FILES["image"]["name"];
} else {
echo "抱歉,上传新文件时出错。";
exit;
}
} else {
echo "上传的文件不是图片。";
exit;
}
}
// 更新数据库
if ($image_url_to_update) {
// 如果有新图片,更新图片路径
$stmt = $conn->prepare("UPDATE products SET name = ?, description = ?, price = ?, image_url = ? WHERE id = ?");
$stmt->bind_param("ssdsi", $name, $description, $price, $image_url_to_update, $id);
} else {
// 如果没有新图片,只更新其他字段
$stmt = $conn->prepare("UPDATE products SET name = ?, description = ?, price = ? WHERE id = ?");
$stmt->bind_param("ssdi", $name, $description, $price, $id);
}
if ($stmt->execute()) {
header("Location: admin/index.php");
exit;
} else {
echo "Error: " . $stmt->error;
}
$stmt->close();
}
}
// 3. 删除产品 (通过GET请求)
elseif (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) {
$id = (int)$_GET['id'];
if (deleteProduct($conn, $id)) {
header("Location: admin/index.php");
exit;
} else {
echo "删除失败。";
}
}
$conn->close();
?>
如何使用
- 环境准备: 确保您的服务器支持PHP和MySQL(XAMPP, WAMP, MAMP 或 LAMP)。
- 创建文件: 按照上面的文件结构,在您的Web服务器根目录下创建所有文件和文件夹。
- 配置数据库:
- 使用phpMyAdmin或其他工具创建
product_showcase数据库。 - 将
CREATE TABLE语句复制并执行。 - 修改
config.php文件中的数据库用户名和密码。
- 使用phpMyAdmin或其他工具创建
- 设置权限:
- 确保
assets/images文件夹有写入权限(chmod 755或chmod 777,在生产环境中建议使用755)。
- 确保
- 访问网站:
- 在浏览器中访问
http://localhost/your-folder-name/index.php查看产品展示首页。 - 访问
http://localhost/your-folder-name/admin/login.php进入后台管理。 - 登录信息:
- 用户名:
admin - 密码:
password123
- 用户名:
- 在浏览器中访问
安全性说明
这个示例代码为了教学清晰,简化了一些安全措施,在实际生产环境中,您还需要注意:

- 密码哈希: 管理员密码不应明文存储,应使用
password_hash()和password_verify()。 - Session管理: 后台登录应使用
$_SESSION来维持登录状态,而不是简单的检查POST数据。 - 防止SQL注入: 虽然这里使用了预处理语句(
prepare),但始终要对所有用户输入进行验证和过滤。 - 防止XSS攻击: 虽然使用了
htmlspecialchars(),但对于更复杂的场景,可以考虑使用更专业的库。 - 文件上传验证: 对上传的文件类型、大小、内容进行更严格的检查,防止上传恶意文件。
希望这份详细的源码对您有帮助!

