PHP: 常量与包含
常量是不变的值。数据库密码、API密钥、网站名称——这些在整个程序运行期间不改变的数据,就该用常量而不是变量。这节课还教你用
include把代码拆成多个文件。
1. define() 与 const
PHP 有两种声明常量的方式:
PHP
<?php
// define():运行时声明(可以在任何地方用)
define("SITE_NAME", "我的博客");
define("MAX_UPLOAD_SIZE", 5 * 1024 * 1024); // 5MB
define("DB_HOST", "localhost");
// const:编译时声明(只能在全局作用域用)
const APP_VERSION = "2.0.0";
const PI = 3.14159;
echo SITE_NAME; // 我的博客(注意没有 $ 符号)
echo APP_VERSION; // 2.0.0
?>
define() |
const |
|
|---|---|---|
| 可用位置 | 任意位置(函数/条件内) | 仅全局作用域 |
| 时间 | 运行时 | 编译时(稍快) |
| 数组 | ✅ PHP 7+ | ✅ PHP 5.6+ |
| 表达式 | ✅ | ❌ 只能简单值 |
| 使用场景 | 配置、条件定义 | 类常量定义 |
💡 提示: 大多数情况优先用
const(性能稍好、代码更清晰)。只有需要动态计算值、或在条件/函数内定义时才用 define()。
(1) 命名规范
常量名全部大写 + 下划线(SCREAMING_SNAKE_CASE):
PHP
<?php
const MAX_LOGIN_ATTEMPTS = 5;
const DEFAULT_LANGUAGE = "zh-CN";
const API_BASE_URL = "https://api.example.com/v1";
?>
(2) 检测常量是否存在
PHP
<?php
if (!defined("SITE_NAME")) {
define("SITE_NAME", "默认网站名");
}
// defined() 检查常量是否已定义
?>
2. 魔术常量
PHP 有一组"魔术常量",它们的值根据使用位置自动变化:
PHP
<?php
// 假设文件路径是:C:\xampp\htdocs\myphp\demo.php
echo __LINE__; // 当前行号:5
echo __FILE__; // 文件完整路径:C:\xampp\htdocs\myphp\demo.php
echo __DIR__; // 文件所在目录:C:\xampp\htdocs\myphp
echo __FUNCTION__; // 当前函数名(函数内)
echo __CLASS__; // 当前类名(类内)
echo __METHOD__; // 当前方法名(方法内)
echo __NAMESPACE__; // 当前命名空间
?>
▶ 示例:__DIR__ 构建可靠路径
PHP
<?php
// ❌ 容易出错的相对路径
$config = include "config.php";
// ✅ 永远是可靠绝对路径的写法
$config = include __DIR__ . "/config.php";
$avatar = __DIR__ . "/uploads/avatars/" . $userId . ".jpg";
?>
💡 提示:
__DIR__ 是开发中最常用的魔术常量。写 include 时用 __DIR__ 拼接路径,确保无论在哪个目录调用脚本都能正确找到文件。
3. include 与 require
把代码拆成多个文件,用 include/require 引入:
PHP
<?php
// config.php
const DB_HOST = "localhost";
const DB_NAME = "myapp";
?>
PHP
<?php
// index.php
require __DIR__ . "/config.php";
echo "数据库地址:" . DB_HOST; // 常量已经可用
?>
include |
require |
|
|---|---|---|
| 文件不存在 | ⚠️ Warning,脚本继续执行 | 🔴 Fatal Error,脚本停止 |
| 用几次 | 可以重复引入 | 可以重复引入 |
| 适用场景 | 不关键的模板 | 关键配置、函数库 |
💡 提示: 规则很简单——能用
require 就用 require。配置、函数库等关键文件出错了就该立刻停止。include 仅用于"有它更好、没它也行"的可选内容。
(1) include_once 和 require_once
防止同一个文件被多次引入:
PHP
<?php
require_once __DIR__ . "/config.php";
require_once __DIR__ . "/config.php"; // 第二次不会重复加载
?>
💡 提示: 函数/类定义文件用
require_once(重复定义会报错),HTML 模板片段用 require(可重复引入)。
4. 预定义常量
PHP 内置了一些全局常量:
PHP
<?php
echo PHP_VERSION; // 8.2.7
echo PHP_INT_MAX; // 9223372036854775807 (64位)
echo PHP_INT_MIN; // -9223372036854775808
echo PHP_FLOAT_MAX; // 1.7976931348623E+308
echo PHP_EOL; // 换行符(\n 或 \r\n 取决于系统)
echo DIRECTORY_SEPARATOR; // \ (Windows) 或 / (Unix)
echo PATH_SEPARATOR; // ; (Windows) 或 : (Unix)
?>
这些常量有助于写跨平台的代码。
5. 模块化实践
把网站拆分为多个文件,用 require 组装:
TEXT
📖 仅展示
myphp/
├── config.php ← 数据库配置、常量
├── functions.php ← 公共函数
├── header.php ← 页面头部 HTML
├── footer.php ← 页面底部 HTML
├── index.php ← 首页
└── about.php ← 关于页
▶ 示例:模块化页面
PHP
<?php
// header.php
?>
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title><?= $pageTitle ?? "我的网站" ?></title>
</head>
<body>
<header>
<h1><?= SITE_NAME ?></h1>
<nav>
<a href="/">首页</a>
<a href="about.php">关于</a>
</nav>
</header>
<main>
PHP
<?php
// footer.php
?>
</main>
<footer>
<p>© <?= date("Y") ?> <?= SITE_NAME ?></p>
</footer>
</body>
</html>
PHP
<?php
// about.php
define("SITE_NAME", "我的博客");
$pageTitle = "关于我们";
require __DIR__ . "/header.php";
?>
<h2>关于我们</h2>
<p>这是一支热爱技术的团队。</p>
<?php
require __DIR__ . "/footer.php";
?>
💡 提示: 这种模块化方式是 PHP 最初的程序设计模式。后续你学 Laravel 时,会发现 Laravel 的 Blade 模板 @include/@extends/@section 就是这种思想的进化版。
❓ 常见问题
Q const 和 define 到底用哪个?
A 全局简单常量用
const(更快更简洁);需要运行时计算或条件定义时用 define();类内只能用 const。Q include 和 require 选哪个?
A 默认用
require——配置和函数库缺失应该立即报错。用 include 的场景极少(可选的广告位、统计代码等不影响主体功能的片段)。Q 为什么明明文件存在,require 还是报错?
A 99% 是路径问题。试试看:先
echo __DIR__ . "/config.php" 确认拼出的完整路径。相对路径是相对于"当前工作目录"而非文件目录,所以用 __DIR__ 拼接最安全。📖 小节
const(全局快)和define()(可动态计算)声明常量- 常量名用
SCREAMING_SNAKE_CASE,无$前缀 - 魔术常量:
__DIR__(目录)、__FILE__(文件)、__LINE__(行号) require文件不存在报 Fatal Error;include只报 Warning__DIR__构建路径最可靠require_once防止重复引入函数/类定义
📝 作业
- 创建一个
config.php,定义网站名、数据库主机、上传目录路径等常量,在另一个 PHP 页面中 require 并使用这些常量输出配置信息。 - 将自己的博客页面拆分为 header.php、footer.php 和首页 index.php,所有 require 用
__DIR__拼接路径。 - 写一段代码,用
defined()检查常量是否已定义,如果未定义则设置默认值。