关注点分离

一个健壮的网页模板系统,其核心思想是 关注点分离

php mysql 网页模板
(图片来源网络,侵删)
  • HTML (结构): 只负责页面的骨架和内容,不包含任何 PHP 逻辑。
  • PHP (逻辑): 负责处理数据、连接数据库、控制页面流程。
  • CSS (样式): 负责页面的外观和布局。
  • JavaScript (交互): 负责页面的动态行为。

我们将采用 PHP 包含文件 的方式来实现模板,这是一种非常流行且易于理解的方法。


项目结构

我们规划一个清晰的项目文件夹结构,这会让你的项目井井有条。

my_website/
├── config.php          # 数据库配置信息
├── db.php              # 数据库连接和查询函数
├── templates/
│   ├── header.php      # 公共头部 (包含 <head>, <header>, 导航栏等)
│   ├── footer.php      # 公共尾部 (包含 <footer>, <script> 标签等)
│   ├── home.php        # 首页内容
│   ├── about.php       # 关于我们页面内容
│   └── article.php     # 文章详情页内容
├── index.php           # 入口文件,根据请求加载不同的页面
└── style.css           # 全局样式表

步骤 1: 数据库准备

假设我们要做一个简单的博客首页,需要从数据库获取文章列表。

  1. 创建数据库和表:

    php mysql 网页模板
    (图片来源网络,侵删)
    CREATE DATABASE my_blog;
    USE my_blog;
    CREATE TABLE articles (
        id INT AUTO_INCREMENT PRIMARY KEY,
        title VARCHAR(255) NOT NULL,
        content TEXT NOT NULL,
        created_at DATETIME DEFAULT CURRENT_TIMESTAMP
    );
  2. 插入一些示例数据:

    INSERT INTO articles (title, content) VALUES
    ('欢迎来到我的博客', '这是我的第一篇博客文章,欢迎您的访问!'),
    ('PHP 学习心得', '今天学习了 PHP 和 MySQL 的结合,感觉非常强大。'),
    ('Web 开发最佳实践', '关注点分离是构建可维护网站的关键。');

步骤 2: PHP 后端逻辑

这是模板系统的“大脑”。

config.php - 安全地存储配置

重要提示: 永远不要把数据库密码等敏感信息直接写在代码里!使用一个单独的配置文件,并确保它不被直接访问。

<?php
// config.php
define('DB_HOST', 'localhost');
define('DB_USER', 'root'); // 你的数据库用户名
define('DB_PASS', 'password'); // 你的数据库密码
define('DB_NAME', 'my_blog');
?>

db.php - 数据库交互

这个文件负责连接数据库,并提供一个简单的函数来执行查询。

php mysql 网页模板
(图片来源网络,侵删)
<?php
// db.php
require_once 'config.php';
// 创建数据库连接
function getDbConnection() {
    try {
        $conn = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASS);
        // 设置 PDO 错误模式为异常
        $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        return $conn;
    } catch(PDOException $e) {
        die("连接失败: " . $e->getMessage());
    }
}
// 获取所有文章
function getArticles() {
    $conn = getDbConnection();
    $stmt = $conn->query("SELECT id, title, created_at FROM articles ORDER BY created_at DESC");
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
// 根据ID获取单篇文章
function getArticleById($id) {
    $conn = getDbConnection();
    $stmt = $conn->prepare("SELECT * FROM articles WHERE id = :id");
    $stmt->bindParam(':id', $id, PDO::PARAM_INT);
    $stmt->execute();
    return $stmt->fetch(PDO::FETCH_ASSOC);
}
?>

步骤 3: 模板文件

模板文件是纯 HTML,我们使用 PHP 的 includeforeach 等语法来嵌入动态内容。

templates/header.php - 公共头部

这个文件会在每个页面的顶部被包含。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0"><?php echo $page_title ?? '默认标题'; ?></title> <!-- 页面标题可动态设置 -->
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <header>
        <nav>
            <a href="index.php">首页</a>
            <a href="about.php">关于我们</a>
        </nav>
    </header>
    <main>

templates/home.php - 首页内容

这个文件只包含首页特有的内容。

<!-- templates/home.php -->
<h1>最新文章</h1>
<div class="article-list">
    <?php
    // 这里会从主页面的 index.php 中接收 $articles 变量
    if (!empty($articles)): 
        foreach ($articles as $article):
    ?>
        <article class="article-item">
            <h2><a href="article.php?id=<?php echo htmlspecialchars($article['id']); ?>"><?php echo htmlspecialchars($article['title']); ?></a></h2>
            <p class="post-meta">发布于: <?php echo date('Y-m-d', strtotime($article['created_at'])); ?></p>
        </article>
    <?php 
        endforeach;
    else:
    ?>
        <p>暂无文章。</p>
    <?php endif; ?>
</div>

注意: htmlspecialchars() 是一个非常重要的安全函数,可以防止 XSS (跨站脚本) 攻击,所有输出到 HTML 的用户数据都应该经过它处理。

templates/footer.php - 公共尾部

这个文件会在每个页面的底部被包含。

    </main>
    <footer>
        <p>&copy; <?php echo date('Y'); ?> 我的博客. All rights reserved.</p>
    </footer>
    <script src="script.js"></script> <!-- 假设的JS文件 -->
</body>
</html>

步骤 4: 整合与入口

我们创建一个 index.php 文件作为所有页面请求的入口,它会根据请求加载不同的模板。

index.php - 主控制器

<?php
// index.php
// 1. 引入必要的文件
require_once 'db.php';
require_once 'templates/header.php';
// 2. 根据URL参数决定加载哪个页面
$page = $_GET['page'] ?? 'home'; // 默认加载首页
// 设置页面标题
$page_title = '首页';
// 3. 处理页面逻辑并加载对应的模板
switch ($page) {
    case 'home':
        // 获取文章数据
        $articles = getArticles();
        // 将数据传递给首页模板
        require_once 'templates/home.php';
        break;
    case 'about':
        $page_title = '关于我们';
        // 加载关于我们页面
        require_once 'templates/about.php';
        break;
    case 'article':
        $page_title = '文章详情';
        $article_id = $_GET['id'] ?? null;
        if ($article_id && is_numeric($article_id)) {
            $article = getArticleById($article_id);
            if ($article) {
                // 将单篇文章数据传递给文章详情模板
                require_once 'templates/article.php';
            } else {
                // 文章不存在,显示404错误
                echo "<h1>文章未找到</h1>";
                echo "<p>抱歉,您访问的文章不存在。</p>";
            }
        } else {
            // ID无效,显示404错误
            http_response_code(404);
            echo "<h1>页面未找到</h1>";
            echo "<p>无效的文章ID。</p>";
        }
        break;
    default:
        // 处理404错误
        http_response_code(404);
        $page_title = '404 - 页面未找到';
        echo "<h1>404 - 页面未找到</h1>";
        echo "<p>抱歉,您访问的页面不存在。</p>";
        break;
}
// 4. 引入公共尾部
require_once 'templates/footer.php';
?>

templates/about.php - 关于我们页面

<!-- templates/about.php -->
<h1>关于我们</h1>
<p>这是一个使用 PHP 和 MySQL 构建的简单博客模板示例。</p>
<p>我们致力于分享有用的技术和生活感悟。</p>

templates/article.php - 文章详情页

<!-- templates/article.php -->
<?php if ($article): ?>
    <article class="full-article">
        <h1><?php echo htmlspecialchars($article['title']); ?></h1>
        <p class="post-meta">发布于: <?php echo date('Y-m-d H:i:s', strtotime($article['created_at'])); ?></p>
        <div class="article-content">
            <p><?php echo nl2br(htmlspecialchars($article['content'])); ?></p>
        </div>
    </article>
<?php endif; ?>

进阶与最佳实践

  1. 模板引擎: 当项目变得复杂时,手写 PHP 混合 HTML 会变得难以维护,这时可以考虑使用专业的 模板引擎,如 TwigBlade (Laravel)

    • 优点: 提供更干净的语法、自动转义、模板继承、布局等功能,能强制实现逻辑与表现的分离。
  2. MVC 架构: 更进一步的架构是 MVC (Model-View-Controller)

    • Model (模型): 负责 数据库交互 (相当于我们的 db.php)。
    • View (视图): 负责 显示HTML (相当于我们的 templates/ 目录)。
    • Controller (控制器): 负责 接收用户请求、调用 Model、处理数据、选择 View 并渲染 (相当于我们的 index.php 的逻辑部分)。 MVC 是大型 Web 应用的标准架构,能让代码结构更清晰、更易于扩展和维护。
  3. 安全性:

    • SQL 注入: 我们使用了 PDO (PHP Data Objects)预处理语句,这是防止 SQL 注入攻击的最佳实践。
    • XSS 攻击: 我们使用了 htmlspecialchars() 函数来过滤输出到 HTML 的数据。
    • 文件包含漏洞: 确保 config.php 等敏感文件不能通过 Web 直接访问(Web 服务器配置会阻止)。
  4. URL 重写: 使用 .htaccess 文件和 mod_rewrite 模块,可以将 index.php?page=article&id=1 这样的 URL 变得更美观,如 article/1,这需要一定的 Apache 服务器配置知识。

通过这个完整的例子,你已经掌握了使用 PHP 和 MySQL 创建网页模板的核心流程:

  1. 分离关注点: HTML 在模板,PHP 在逻辑文件。
  2. 使用 include/require 来组装页面。
  3. 数据库操作 通过独立的函数完成。
  4. 入口文件 (index.php) 作为总控制器,分发请求。
  5. 始终注意安全,使用 PDO 和 htmlspecialchars

这个模板系统是构建任何动态网站(如博客、CMS、电商网站)的基础,你可以基于这个框架,不断添加新的页面和功能。