凌峰创科服务平台

PHP产品展示网站源码如何快速搭建?

功能特点

  • 产品展示: 以卡片形式在首页展示所有产品。
  • 产品详情: 点击产品可查看大图、详细描述和价格。
  • 后台管理: 一个简单的管理界面,可以添加、编辑和删除产品。
  • 文件上传: 支持上传产品图片。
  • 响应式设计: 适配桌面和移动设备。

第一步:数据库设计

您需要创建一个MySQL数据库和一张表来存储产品信息。

PHP产品展示网站源码如何快速搭建?-图1
(图片来源网络,侵删)
  1. 创建数据库(例如命名为 product_showcase)。
  2. 执行以下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>&copy; <?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">&larr; 返回列表</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();
?>

如何使用

  1. 环境准备: 确保您的服务器支持PHP和MySQL(XAMPP, WAMP, MAMP 或 LAMP)。
  2. 创建文件: 按照上面的文件结构,在您的Web服务器根目录下创建所有文件和文件夹。
  3. 配置数据库:
    • 使用phpMyAdmin或其他工具创建 product_showcase 数据库。
    • CREATE TABLE 语句复制并执行。
    • 修改 config.php 文件中的数据库用户名和密码。
  4. 设置权限:
    • 确保 assets/images 文件夹有写入权限(chmod 755chmod 777,在生产环境中建议使用 755)。
  5. 访问网站:
    • 在浏览器中访问 http://localhost/your-folder-name/index.php 查看产品展示首页。
    • 访问 http://localhost/your-folder-name/admin/login.php 进入后台管理。
    • 登录信息:
      • 用户名: admin
      • 密码: password123

安全性说明

这个示例代码为了教学清晰,简化了一些安全措施,在实际生产环境中,您还需要注意:

PHP产品展示网站源码如何快速搭建?-图2
(图片来源网络,侵删)
  • 密码哈希: 管理员密码不应明文存储,应使用 password_hash()password_verify()
  • Session管理: 后台登录应使用 $_SESSION 来维持登录状态,而不是简单的检查POST数据。
  • 防止SQL注入: 虽然这里使用了预处理语句(prepare),但始终要对所有用户输入进行验证和过滤。
  • 防止XSS攻击: 虽然使用了 htmlspecialchars(),但对于更复杂的场景,可以考虑使用更专业的库。
  • 文件上传验证: 对上传的文件类型、大小、内容进行更严格的检查,防止上传恶意文件。

希望这份详细的源码对您有帮助!

PHP产品展示网站源码如何快速搭建?-图3
(图片来源网络,侵删)
分享:
扫描分享到社交APP
上一篇
下一篇