PHP include 和 require 语句
PHP include 和 require 语句中文讲解
什么是 include 和 require 语句?
include
和 require
是 PHP 中用于在脚本中引入外部文件的语句。它们允许开发者将代码模块化,将公共代码(如配置、函数、类或 HTML 片段)存储在单独文件中,并在需要时引入。两者功能类似,但错误处理方式不同,适合在 Web 开发中复用代码或组织项目结构。
为什么使用 include 和 require?
- 代码复用:避免重复编写相同代码,如页眉、页脚或数据库连接。
- 模块化:将代码分解为独立文件,便于维护和协作。
- 组织性:结合命名空间和目录结构,清晰管理大型项目。
- 典型场景:加载配置文件、模板、函数库或类文件。
基本语法
include 'filename.php';
require 'filename.php';
- filename:要引入的文件路径(相对或绝对路径)。
- 变体:
include_once
:确保文件只引入一次。require_once
:类似include_once
,但使用require
的错误处理机制。
include vs require
- 错误处理:
include
:文件不存在或无法加载时,触发警告(Warning),脚本继续执行。require
:文件不存在或无法加载时,触发致命错误(Fatal Error),脚本终止。- 使用场景:
include
:适合非关键文件(如可选模板),允许脚本在文件缺失时继续运行。require
:适合关键文件(如数据库配置),文件缺失会导致功能失效。- 性能:两者性能差异微小,但
*_once
变体会检查文件是否已引入,略增加开销。
基本示例
- 使用 include
假设有一个文件header.php
:
<!-- header.php -->
<header>
<h1>欢迎来到我的网站</h1>
</header>
主文件 index.php
:
<?php
include 'header.php';
echo "这是页面内容";
?>
输出:
<header>
<h1>欢迎来到我的网站</h1>
</header>
这是页面内容
- 使用 require
配置文件config.php
:
<?php
define('DB_HOST', 'localhost');
define('DB_USER', 'user');
define('DB_PASS', 'pass');
?>
主文件 db_connect.php
:
<?php
require 'config.php';
$pdo = new PDO("mysql:host=" . DB_HOST, DB_USER, DB_PASS);
?>
- 使用 include_once/require_once
防止重复引入导致的重定义错误:
<?php
// functions.php
function sayHello() {
echo "Hello!";
}
?>
<?php
include_once 'functions.php';
include_once 'functions.php'; // 不会重复引入
sayHello(); // 输出:Hello!
?>
结合表单处理示例
以下是一个使用 include
和 require
处理表单的完整示例,展示模块化代码结构。
- 配置文件 (
config.php
):
<?php
// 数据库配置
define('DB_HOST', 'localhost');
define('DB_NAME', 'test');
define('DB_USER', 'user');
define('DB_PASS', 'pass');
?>
- 数据库连接 (
db.php
):
<?php
require 'config.php'; // 必须加载配置
try {
$pdo = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASS);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("数据库连接失败: " . $e->getMessage());
}
?>
- HTML 表单 (
form.html
):
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>用户注册</title>
<style>
.error { color: red; }
label { display: inline-block; width: 100px; }
input { margin-bottom: 10px; }
</style>
</head>
<body>
<h2>用户注册</h2>
<?php include 'errors.php'; // 包含错误显示 ?>
<form action="process.php" method="post">
<?php
session_start();
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
?>
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($_SESSION['csrf_token']); ?>">
<label for="name">姓名*:</label>
<input type="text" id="name" name="name" value="<?php echo isset($_POST['name']) ? htmlspecialchars($_POST['name']) : ''; ?>">
<br>
<label for="email">邮箱*:</label>
<input type="email" id="email" name="email" value="<?php echo isset($_POST['email']) ? htmlspecialchars($_POST['email']) : ''; ?>">
<br>
<input type="submit" value="注册">
<p>* 表示必需字段</p>
</form>
</body>
</html>
- 错误显示文件 (
errors.php
):
<?php
if (!empty($errors)) {
echo "<div class='error'><ul>";
foreach ($errors as $error) {
echo "<li>$error</li>";
}
echo "</ul></div>";
}
?>
- 处理脚本 (
process.php
):
<?php
session_start();
$errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// 验证 CSRF 令牌
if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
$errors[] = "CSRF 验证失败";
} else {
// 清理输入
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$name = filter_var($name, FILTER_SANITIZE_STRING);
$email = filter_var($email, FILTER_SANITIZE_EMAIL);
// 验证
if (empty($name)) {
$errors[] = "姓名是必需字段";
}
if (empty($email)) {
$errors[] = "邮箱是必需字段";
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = "无效的邮箱格式";
}
// 如果没有错误,保存数据
if (empty($errors)) {
require 'db.php'; // 加载数据库连接
try {
$stmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (:name, :email)");
$stmt->execute(['name' => $name, 'email' => $email]);
echo "注册成功!";
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
exit;
} catch (PDOException $e) {
$errors[] = "数据库错误: " . $e->getMessage();
}
}
}
}
// 显示表单和错误
include 'form.html';
?>
- 数据库表结构 (
users
表):
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
关键点解析
- 模块化:
config.php
(配置)、db.php
(数据库连接)、errors.php
(错误显示)分离代码,提高可维护性。 - include vs require:
- 使用
require 'config.php'
和require 'db.php'
,因为数据库连接是关键功能,失败应终止脚本。 - 使用
include 'errors.php'
和include 'form.html'
,因为错误显示和表单是可选的,失败不影响核心逻辑。 - 安全性:
htmlspecialchars()
防止 XSS。- PDO 预处理语句防止 SQL 注入。
- CSRF 令牌防止跨站请求伪造。
- 错误处理:集中存储错误,统一显示,结合
include
回显表单。
路径处理
- 相对路径:如
include 'header.php'
,基于当前文件位置。 - 绝对路径:使用
__DIR__
确保路径正确:
include __DIR__ . '/includes/header.php';
- 文件不存在:
include
:触发警告,继续执行。require
:触发致命错误,停止执行。
include 'nonexistent.php'; // 警告,继续
require 'nonexistent.php'; // 致命错误,停止
最佳实践
- 选择合适的语句:
- 用
require
加载关键文件(如数据库配置)。 - 用
include
加载非关键文件(如模板)。 - 用
*_once
防止重复引入(如函数库)。 - 路径管理:使用
__DIR__
或自动加载(PSR-4)避免路径问题。 - 错误检查:检查文件是否存在:
if (file_exists('config.php')) {
require 'config.php';
} else {
die("配置文件缺失");
}
- 模块化设计:将功能拆分为独立文件,结合命名空间和 Composer。
- 安全性:清理用户输入,防止注入攻击。
参考资源
- PHP 官方手册 – include:详细说明。
- 菜鸟教程 – PHP include 和 require:初学者教程。
- OWASP 安全指南:Web 安全最佳实践。
总结
include
和 require
是 PHP 实现代码复用和模块化的核心工具,require
适合关键依赖,include
适合可选内容。结合 *_once
防止重复引入,使用 __DIR__
确保路径正确,可以构建清晰、安全的 Web 应用。上述示例展示了如何将 include
和 require
应用于表单处理,涵盖验证、数据库交互和安全性,适合实际开发场景。