Skip to content

第 15 章:完整实战项目(企业级风格)

实战 4:个人博客系统

项目概述

个人博客系统是一个完整的 Web 应用,包括文章列表、文章详情、分类管理、后台登录和文章增删改查功能。

技术栈

  • PHP
  • MySQL
  • HTML/CSS
  • Session

功能模块

  1. 前台展示
    • 文章列表
    • 文章详情
    • 分类筛选
  2. 后台管理
    • 管理员登录
    • 文章管理(增删改查)
    • 分类管理

数据库设计

sql
CREATE DATABASE IF NOT EXISTS blog CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

USE blog;

-- 管理员表
CREATE TABLE IF NOT EXISTS admins (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL UNIQUE,
    password VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 分类表
CREATE TABLE IF NOT EXISTS categories (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 文章表
CREATE TABLE IF NOT EXISTS articles (
    id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(200) NOT NULL,
    content TEXT NOT NULL,
    category_id INT,
    admin_id INT,
    views INT DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (category_id) REFERENCES categories(id),
    FOREIGN KEY (admin_id) REFERENCES admins(id)
);

-- 插入默认管理员
INSERT INTO admins (username, password) VALUES ('admin', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi');
-- 密码是 'password'

-- 插入默认分类
INSERT INTO categories (name) VALUES ('技术'), ('生活'), ('随笔');

-- 插入示例文章
INSERT INTO articles (title, content, category_id, admin_id) VALUES
('PHP 入门教程', 'PHP 是一种服务器端脚本语言...', 1, 1),
('MySQL 基础知识', 'MySQL 是一种关系型数据库...', 1, 1),
('我的学习心得', '学习编程需要坚持不懈...', 2, 1);

项目结构

blog/
├── index.php          # 首页(文章列表)
├── article.php        # 文章详情
├── admin/
│   ├── login.php      # 后台登录
│   ├── logout.php     # 退出登录
│   ├── index.php      # 后台首页
│   ├── articles.php   # 文章管理
│   └── categories.php # 分类管理
├── config.php         # 数据库配置
└── style.css          # 样式文件

核心代码实现

1. 数据库配置文件 (config.php)

php
<?php
// 数据库配置
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', '');
define('DB_NAME', 'blog');

// 连接数据库
function getConnection() {
    $conn = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
    if (!$conn) {
        die("连接失败: " . mysqli_connect_error());
    }
    mysqli_set_charset($conn, 'utf8mb4');
    return $conn;
}

// 初始化数据库
function initDatabase() {
    $conn = mysqli_connect(DB_HOST, DB_USER, DB_PASS);
    
    // 创建数据库
    $sql = "CREATE DATABASE IF NOT EXISTS `" . DB_NAME . "` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci";
    mysqli_query($conn, $sql);
    
    mysqli_select_db($conn, DB_NAME);
    
    // 创建表
    $sql = "CREATE TABLE IF NOT EXISTS admins (
        id INT PRIMARY KEY AUTO_INCREMENT,
        username VARCHAR(50) NOT NULL UNIQUE,
        password VARCHAR(255) NOT NULL,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )";
    mysqli_query($conn, $sql);
    
    $sql = "CREATE TABLE IF NOT EXISTS categories (
        id INT PRIMARY KEY AUTO_INCREMENT,
        name VARCHAR(50) NOT NULL,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )";
    mysqli_query($conn, $sql);
    
    $sql = "CREATE TABLE IF NOT EXISTS articles (
        id INT PRIMARY KEY AUTO_INCREMENT,
        title VARCHAR(200) NOT NULL,
        content TEXT NOT NULL,
        category_id INT,
        admin_id INT,
        views INT DEFAULT 0,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )";
    mysqli_query($conn, $sql);
    
    // 插入默认数据
    $sql = "SELECT COUNT(*) as count FROM admins";
    $result = mysqli_query($conn, $sql);
    $row = mysqli_fetch_assoc($result);
    if ($row['count'] == 0) {
        $hashed_password = password_hash('password', PASSWORD_DEFAULT);
        $sql = "INSERT INTO admins (username, password) VALUES ('admin', '$hashed_password')";
        mysqli_query($conn, $sql);
    }
    
    $sql = "SELECT COUNT(*) as count FROM categories";
    $result = mysqli_query($conn, $sql);
    $row = mysqli_fetch_assoc($result);
    if ($row['count'] == 0) {
        $sql = "INSERT INTO categories (name) VALUES ('技术'), ('生活'), ('随笔')";
        mysqli_query($conn, $sql);
    }
    
    $sql = "SELECT COUNT(*) as count FROM articles";
    $result = mysqli_query($conn, $sql);
    $row = mysqli_fetch_assoc($result);
    if ($row['count'] == 0) {
        $sql = "INSERT INTO articles (title, content, category_id, admin_id) VALUES
        ('PHP 入门教程', 'PHP 是一种服务器端脚本语言,特别适合 Web 开发。它简单易学,功能强大,是开发动态网站的首选语言之一。', 1, 1),
        ('MySQL 基础知识', 'MySQL 是一种关系型数据库管理系统,广泛应用于 Web 应用中。它开源免费,性能稳定,是 PHP 的最佳搭档。', 1, 1),
        ('我的学习心得', '学习编程需要坚持不懈,每天进步一点点。遇到问题不要怕,多看文档,多写代码,多思考。', 2, 1)";
        mysqli_query($conn, $sql);
    }
    
    mysqli_close($conn);
}

// 初始化数据库
initDatabase();
?>

2. 首页 (index.php)

php
<?php
require_once 'config.php';

$conn = getConnection();

// 获取分类
$category_id = isset($_GET['category']) ? (int)$_GET['category'] : 0;

// 查询文章
if ($category_id > 0) {
    $sql = "SELECT a.*, c.name as category_name 
            FROM articles a 
            LEFT JOIN categories c ON a.category_id = c.id 
            WHERE a.category_id = $category_id 
            ORDER BY a.created_at DESC";
} else {
    $sql = "SELECT a.*, c.name as category_name 
            FROM articles a 
            LEFT JOIN categories c ON a.category_id = c.id 
            ORDER BY a.created_at DESC";
}

$result = mysqli_query($conn, $sql);

// 查询所有分类
$categories_sql = "SELECT * FROM categories ORDER BY name";
$categories_result = mysqli_query($conn, $categories_sql);
?>

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>我的博客</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { font-family: Arial, sans-serif; line-height: 1.6; background-color: #f5f5f5; }
        .container { max-width: 1000px; margin: 0 auto; padding: 20px; }
        header { background-color: #333; color: white; padding: 20px; margin-bottom: 20px; }
        header h1 { margin-bottom: 10px; }
        nav { background-color: #444; padding: 10px; }
        nav a { color: white; text-decoration: none; margin-right: 15px; }
        nav a:hover { color: #ddd; }
        .content { display: flex; gap: 20px; }
        .main { flex: 3; }
        .sidebar { flex: 1; background-color: white; padding: 15px; border-radius: 5px; }
        .article { background-color: white; padding: 20px; margin-bottom: 20px; border-radius: 5px; }
        .article h2 { margin-bottom: 10px; }
        .article h2 a { color: #333; text-decoration: none; }
        .article h2 a:hover { color: #007bff; }
        .article-meta { color: #666; font-size: 14px; margin-bottom: 10px; }
        .article-content { color: #333; }
        .sidebar h3 { margin-bottom: 15px; padding-bottom: 10px; border-bottom: 2px solid #007bff; }
        .category-list { list-style: none; }
        .category-list li { margin-bottom: 8px; }
        .category-list a { color: #333; text-decoration: none; }
        .category-list a:hover { color: #007bff; }
        footer { text-align: center; padding: 20px; margin-top: 20px; background-color: #333; color: white; }
    </style>
</head>
<body>
    <header>
        <div class="container">
            <h1>我的博客</h1>
            <p>记录学习与生活的点滴</p>
        </div>
    </header>
    
    <nav>
        <div class="container">
            <a href="index.php">首页</a>
            <a href="admin/login.php">后台管理</a>
        </div>
    </nav>
    
    <div class="container">
        <div class="content">
            <div class="main">
                <?php if (mysqli_num_rows($result) > 0): ?>
                    <?php while ($row = mysqli_fetch_assoc($result)): ?>
                        <div class="article">
                            <h2><a href="article.php?id=<?php echo $row['id']; ?>"><?php echo htmlspecialchars($row['title']); ?></a></h2>
                            <div class="article-meta">
                                分类:<?php echo htmlspecialchars($row['category_name']); ?> | 
                                浏览:<?php echo $row['views']; ?> | 
                                时间:<?php echo date('Y-m-d', strtotime($row['created_at'])); ?>
                            </div>
                            <div class="article-content">
                                <?php echo mb_substr(strip_tags($row['content']), 0, 200) . '...'; ?>
                            </div>
                        </div>
                    <?php endwhile; ?>
                <?php else: ?>
                    <div class="article">
                        <p>暂无文章</p>
                    </div>
                <?php endif; ?>
            </div>
            
            <div class="sidebar">
                <h3>分类</h3>
                <ul class="category-list">
                    <li><a href="index.php">全部</a></li>
                    <?php while ($cat = mysqli_fetch_assoc($categories_result)): ?>
                        <li><a href="index.php?category=<?php echo $cat['id']; ?>"><?php echo htmlspecialchars($cat['name']); ?></a></li>
                    <?php endwhile; ?>
                </ul>
            </div>
        </div>
    </div>
    
    <footer>
        <p>&copy; <?php echo date('Y'); ?> 我的博客. All rights reserved.</p>
    </footer>
    
    <?php mysqli_close($conn); ?>
</body>
</html>

3. 文章详情页 (article.php)

php
<?php
require_once 'config.php';

$conn = getConnection();

// 获取文章 ID
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;

if ($id <= 0) {
    die('文章不存在');
}

// 增加浏览量
$sql = "UPDATE articles SET views = views + 1 WHERE id = $id";
mysqli_query($conn, $sql);

// 查询文章
$sql = "SELECT a.*, c.name as category_name 
        FROM articles a 
        LEFT JOIN categories c ON a.category_id = c.id 
        WHERE a.id = $id";
$result = mysqli_query($conn, $sql);

if (mysqli_num_rows($result) == 0) {
    die('文章不存在');
}

$article = mysqli_fetch_assoc($result);
?>

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title><?php echo htmlspecialchars($article['title']); ?> - 我的博客</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { font-family: Arial, sans-serif; line-height: 1.6; background-color: #f5f5f5; }
        .container { max-width: 800px; margin: 0 auto; padding: 20px; }
        header { background-color: #333; color: white; padding: 20px; margin-bottom: 20px; }
        header h1 { margin-bottom: 10px; }
        nav { background-color: #444; padding: 10px; }
        nav a { color: white; text-decoration: none; margin-right: 15px; }
        nav a:hover { color: #ddd; }
        .article { background-color: white; padding: 30px; border-radius: 5px; }
        .article h1 { margin-bottom: 20px; }
        .article-meta { color: #666; font-size: 14px; margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid #eee; }
        .article-content { line-height: 1.8; }
        footer { text-align: center; padding: 20px; margin-top: 20px; background-color: #333; color: white; }
    </style>
</head>
<body>
    <header>
        <div class="container">
            <h1>我的博客</h1>
            <p>记录学习与生活的点滴</p>
        </div>
    </header>
    
    <nav>
        <div class="container">
            <a href="index.php">首页</a>
            <a href="admin/login.php">后台管理</a>
        </div>
    </nav>
    
    <div class="container">
        <div class="article">
            <h1><?php echo htmlspecialchars($article['title']); ?></h1>
            <div class="article-meta">
                分类:<?php echo htmlspecialchars($article['category_name']); ?> | 
                浏览:<?php echo $article['views']; ?> | 
                时间:<?php echo date('Y-m-d H:i', strtotime($article['created_at'])); ?>
            </div>
            <div class="article-content">
                <?php echo nl2br(htmlspecialchars($article['content'])); ?>
            </div>
        </div>
    </div>
    
    <footer>
        <p>&copy; <?php echo date('Y'); ?> 我的博客. All rights reserved.</p>
    </footer>
    
    <?php mysqli_close($conn); ?>
</body>
</html>

4. 后台登录 (admin/login.php)

php
<?php
session_start();
require_once '../config.php';

// 检查是否已登录
if (isset($_SESSION['admin_id'])) {
    header('Location: index.php');
    exit;
}

$conn = getConnection();
$error = '';

if (isset($_POST['login'])) {
    $username = mysqli_real_escape_string($conn, $_POST['username']);
    $password = $_POST['password'];
    
    if (empty($username) || empty($password)) {
        $error = '用户名和密码不能为空';
    } else {
        $sql = "SELECT * FROM admins WHERE username = '$username'";
        $result = mysqli_query($conn, $sql);
        
        if (mysqli_num_rows($result) > 0) {
            $admin = mysqli_fetch_assoc($result);
            if (password_verify($password, $admin['password'])) {
                $_SESSION['admin_id'] = $admin['id'];
                $_SESSION['admin_username'] = $admin['username'];
                header('Location: index.php');
                exit;
            } else {
                $error = '密码错误';
            }
        } else {
            $error = '用户名不存在';
        }
    }
}

mysqli_close($conn);
?>

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>后台登录 - 我的博客</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { font-family: Arial, sans-serif; background-color: #f5f5f5; display: flex; justify-content: center; align-items: center; height: 100vh; }
        .login-form { background-color: white; padding: 30px; border-radius: 5px; width: 350px; }
        .login-form h2 { text-align: center; margin-bottom: 20px; }
        input { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #ddd; border-radius: 4px; }
        button { width: 100%; padding: 10px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; }
        button:hover { background-color: #0056b3; }
        .error { color: red; text-align: center; margin-bottom: 10px; }
    </style>
</head>
<body>
    <div class="login-form">
        <h2>后台登录</h2>
        <?php if (!empty($error)): ?>
            <p class="error"><?php echo $error; ?></p>
        <?php endif; ?>
        <form method="post">
            <input type="text" name="username" placeholder="用户名" required><br>
            <input type="password" name="password" placeholder="密码" required><br>
            <button type="submit" name="login">登录</button>
        </form>
        <p style="text-align: center; margin-top: 15px; color: #666;">
            默认账号:admin / password
        </p>
    </div>
</body>
</html>

5. 后台首页 (admin/index.php)

php
<?php
session_start();
require_once '../config.php';

// 检查是否登录
if (!isset($_SESSION['admin_id'])) {
    header('Location: login.php');
    exit;
}

$conn = getConnection();

// 统计数据
$sql = "SELECT COUNT(*) as count FROM articles";
$result = mysqli_query($conn, $sql);
$article_count = mysqli_fetch_assoc($result)['count'];

$sql = "SELECT COUNT(*) as count FROM categories";
$result = mysqli_query($conn, $sql);
$category_count = mysqli_fetch_assoc($result)['count'];

$sql = "SELECT SUM(views) as total FROM articles";
$result = mysqli_query($conn, $sql);
$total_views = mysqli_fetch_assoc($result)['total'] ?? 0;

// 最新文章
$sql = "SELECT * FROM articles ORDER BY created_at DESC LIMIT 5";
$recent_articles = mysqli_query($conn, $sql);
?>

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>后台管理 - 我的博客</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { font-family: Arial, sans-serif; background-color: #f5f5f5; }
        .header { background-color: #333; color: white; padding: 15px 20px; }
        .header h1 { display: inline; }
        .header .user { float: right; }
        .header .user a { color: white; margin-left: 15px; }
        .nav { background-color: #444; padding: 10px 20px; }
        .nav a { color: white; text-decoration: none; margin-right: 20px; }
        .nav a:hover { color: #ddd; }
        .container { padding: 20px; }
        .stats { display: flex; gap: 20px; margin-bottom: 30px; }
        .stat-box { background-color: white; padding: 20px; border-radius: 5px; flex: 1; text-align: center; }
        .stat-box h3 { color: #666; margin-bottom: 10px; }
        .stat-box .number { font-size: 32px; font-weight: bold; color: #007bff; }
        .recent-articles { background-color: white; padding: 20px; border-radius: 5px; }
        .recent-articles h3 { margin-bottom: 15px; }
        table { width: 100%; border-collapse: collapse; }
        th, td { padding: 10px; text-align: left; border-bottom: 1px solid #ddd; }
        th { background-color: #f5f5f5; }
    </style>
</head>
<body>
    <div class="header">
        <h1>博客后台管理</h1>
        <div class="user">
            欢迎,<?php echo $_SESSION['admin_username']; ?>
            <a href="logout.php">退出</a>
        </div>
    </div>
    
    <div class="nav">
        <a href="index.php">首页</a>
        <a href="articles.php">文章管理</a>
        <a href="categories.php">分类管理</a>
        <a href="../index.php" target="_blank">查看网站</a>
    </div>
    
    <div class="container">
        <div class="stats">
            <div class="stat-box">
                <h3>文章总数</h3>
                <div class="number"><?php echo $article_count; ?></div>
            </div>
            <div class="stat-box">
                <h3>分类总数</h3>
                <div class="number"><?php echo $category_count; ?></div>
            </div>
            <div class="stat-box">
                <h3>总浏览量</h3>
                <div class="number"><?php echo $total_views; ?></div>
            </div>
        </div>
        
        <div class="recent-articles">
            <h3>最新文章</h3>
            <table>
                <tr>
                    <th>ID</th>
                    <th>标题</th>
                    <th>浏览量</th>
                    <th>发布时间</th>
                </tr>
                <?php while ($row = mysqli_fetch_assoc($recent_articles)): ?>
                    <tr>
                        <td><?php echo $row['id']; ?></td>
                        <td><?php echo htmlspecialchars($row['title']); ?></td>
                        <td><?php echo $row['views']; ?></td>
                        <td><?php echo date('Y-m-d H:i', strtotime($row['created_at'])); ?></td>
                    </tr>
                <?php endwhile; ?>
            </table>
        </div>
    </div>
    
    <?php mysqli_close($conn); ?>
</body>
</html>

访问项目

  1. 将所有文件保存到网站根目录的 blog 文件夹中
  2. 打开浏览器,访问 http://localhost/blog/
  3. 点击「后台管理」,使用账号 admin 和密码 password 登录
  4. 测试文章和分类管理功能

实战 5:简单后台管理系统(CMS)

项目概述

简单后台管理系统(CMS)是一个通用的内容管理系统,可以用于管理各种类型的内容。

技术栈

  • PHP
  • MySQL
  • HTML/CSS
  • Bootstrap
  • Session

功能模块

  1. 用户管理
  2. 内容管理
  3. 系统设置

实现步骤

由于篇幅限制,这里只提供核心思路和关键代码片段。

1. 数据库设计

sql
CREATE DATABASE IF NOT EXISTS cms CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

USE cms;

-- 用户表
CREATE TABLE IF NOT EXISTS users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL UNIQUE,
    password VARCHAR(255) NOT NULL,
    email VARCHAR(100),
    role ENUM('admin', 'editor') DEFAULT 'editor',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 内容表
CREATE TABLE IF NOT EXISTS contents (
    id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(200) NOT NULL,
    content TEXT,
    type VARCHAR(50) DEFAULT 'page',
    status ENUM('draft', 'published') DEFAULT 'draft',
    author_id INT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (author_id) REFERENCES users(id)
);

2. 核心功能

php
<?php
// 用户认证
function authenticate($username, $password) {
    $user = getUserByUsername($username);
    if ($user && password_verify($password, $user['password'])) {
        return $user;
    }
    return false;
}

// 权限检查
function checkPermission($required_role) {
    if (!isset($_SESSION['user_role']) || $_SESSION['user_role'] !== $required_role) {
        header('HTTP/1.0 403 Forbidden');
        die('没有权限访问');
    }
}

// 内容管理
function createContent($title, $content, $type, $author_id) {
    $sql = "INSERT INTO contents (title, content, type, author_id) VALUES (?, ?, ?, ?)";
    // 执行 SQL...
}

function updateContent($id, $title, $content) {
    $sql = "UPDATE contents SET title = ?, content = ?, updated_at = NOW() WHERE id = ?";
    // 执行 SQL...
}

function deleteContent($id) {
    $sql = "DELETE FROM contents WHERE id = ?";
    // 执行 SQL...
}
?>

小结

通过本章的学习,你完成了两个完整的实战项目:个人博客系统和简单后台管理系统。这些项目涵盖了 PHP Web 开发的核心功能,包括数据库设计、用户认证、内容管理等。通过这些项目的实践,你可以将之前学习的 PHP 知识综合运用,为实际项目开发积累经验。在实际开发中,你还可以使用 PHP 框架(如 Laravel、CodeIgniter)来提高开发效率和代码质量。

© 2026 编程马·菜鸟教程 版权所有