PHP 常量 (Constants)
常量(Constants)是用于存储简单值的标识符。顾名思义,常量一旦被定义,在脚本的整个执行过程中就不能被改变或取消定义。它们与变量的最大区别就在于其值是固定不变的。
PHP 提供了两种主要的方式来定义常量:define() 函数和 const 关键字。
1. 使用 define() 定义常量
define() 是一个全局函数,用于在运行时(runtime)定义常量。它可以在类的定义之外使用,非常适合用来定义在整个脚本中都可以访问的全局常量。
define() 的语法如下:
define(string $name, mixed $value, bool $case_insensitive = false): bool$name:常量的名称。通常的约定是使用全大写字母和下划线来命名常量。$value:常量的值。这可以是一个标量值(整数、浮点数、字符串、布尔值)、一个数组或一个资源。$case_insensitive:一个可选的布尔值参数。如果设置为true,则该常量将不区分大小写。默认值为false,即常量是区分大小写的。在现代 PHP 开发中,强烈不建议使用true,因为这很容易引起代码混乱。
使用 define() 定义的常量在全局作用域中都有效。
1.1 define() 基础示例
<?php
// 定义一个区分大小写的常量,用于存储应用名称
define('APP_NAME', '我的超级应用');
// 定义一个数据库主机常量
define('DB_HOST', 'localhost');
// 定义一个最大文件大小常量(以字节为单位)
define('MAX_FILE_SIZE', 1024 * 1024 * 5); // 5 MB
echo '应用名称: ' . APP_NAME . '<br>';
echo '数据库主机: ' . DB_HOST . '<br>';
echo '最大文件大小: ' . MAX_FILE_SIZE . ' 字节<br>';
// 尝试重新定义一个已存在的常量会导致致命错误 (Fatal error)
// define('APP_NAME', '另一个应用'); // 这行代码会报错
// 访问一个不存在的常量
// echo NON_EXISTENT_CONSTANT; // 这会抛出一个 Notice 警告,并且什么都不输出
?>在这个例子中,APP_NAME、DB_HOST 和 MAX_FILE_SIZE 被定义为常量。一旦定义,它们的值就无法再被修改。
1.2 define() 与数组
从 PHP 7 开始,define() 也可以用来定义包含数组值的常量。
<?php
// 定义一个数组常量,存储允许的图片类型
define('ALLOWED_IMAGE_TYPES', ['image/jpeg', 'image/png', 'image/gif']);
// 访问数组常量中的特定元素
echo '第一个允许的图片类型: ' . ALLOWED_IMAGE_TYPES[0] . '<br>';
// 遍历数组常量
echo '所有允许的图片类型:<br>';
foreach (ALLOWED_IMAGE_TYPES as $type) {
echo '- ' . $type . '<br>';
}
?>这个例子展示了如何定义一个数组常量,并访问和遍历它的元素。这对于存储一组固定的列表值非常有用。
1.3 在条件语句中使用 define()
使用 define() 定义常量的一大优势是,它可以在条件语句块内部执行。这允许你根据特定条件(例如不同的环境设置)动态地定义常量。
<?php
$environment = 'development'; // 可能是 'production' (生产环境), 'staging' (测试环境) 等
if ($environment === 'development') {
define('DEBUG_MODE', true);
define('API_BASE_URL', 'http://dev.api.example.com');
} else {
define('DEBUG_MODE', false);
define('API_BASE_URL', 'https://api.example.com');
}
echo '调试模式: ' . (DEBUG_MODE ? '已开启' : '已关闭') . '<br>';
echo 'API 基础地址: ' . API_BASE_URL . '<br>';
?>在这里,DEBUG_MODE 和 API_BASE_URL 会根据 $environment 变量的值被赋予不同的内容。这是管理项目配置信息的一种常见模式。
2. 使用 const 关键字定义常量
const 关键字用于在编译时(compile time)定义常量。这意味着使用 const 定义的常量必须声明在脚本的顶层作用域,或者在类/接口的内部(作为类常量,我们将在后续章节详细讲解)。
你不能在函数、循环、if 语句或 try...catch 块内部使用 const。
const 的语法更加简洁:
const NAME = value;NAME:常量的名称,通常也是全大写字母加下划线。value:常量的值。可以是标量值、数组或资源。在较老的 PHP 版本(5.6 之前)中,const 的值不支持表达式(例如函数调用、数学运算)。但在现代 PHP(PHP 5.6+)中,const 允许使用标量表达式。对于数组,它的工作原理与 define() 类似。
使用 const 定义的常量始终是区分大小写的。
2.1 const 基础示例
<?php
// 定义一个网站域名的常量
const WEBSITE_DOMAIN = 'example.com';
// 定义一个默认主题的常量
const DEFAULT_THEME = 'dark';
// 定义一个数字常量
const PI = 3.14159;
echo '网站域名: ' . WEBSITE_DOMAIN . '<br>';
echo '默认主题: ' . DEFAULT_THEME . '<br>';
echo '圆周率 PI 的值: ' . PI . '<br>';
// 尝试在函数内部定义 const 会导致解析错误 (Parse error)
/*
function myFunction() {
const MY_CONSTANT = 'value'; // 解析错误
}
*/
?>在这个例子中,WEBSITE_DOMAIN、DEFAULT_THEME 和 PI 使用 const 定义,它们的值在代码编译时就已经确定。
2.2 const 配合表达式 (PHP 5.6+)
现代 PHP 版本(5.6 及更高)允许 const 使用标量表达式来定义值。
<?php
// 使用数学表达式定义常量
const TWO_PI = 2 * PI; // 注意:PI 必须提前定义,例如 const PI = 3.14159;
const MAX_DIMENSION = 1920 + 1080; // 简单的算术运算
echo '两倍的 PI: ' . TWO_PI . '<br>';
echo '最大尺寸总和: ' . MAX_DIMENSION . '<br>';
// 在表达式中使用其他已定义的常量
const APP_VERSION = '1.0';
const APP_FULL_VERSION = APP_VERSION . '.0-beta'; // 字符串拼接
echo '应用完整版本: ' . APP_FULL_VERSION . '<br>';
?>这说明了 const 可以使用简单的表达式(包括其他已定义的常量)来计算其最终的值。
2.3 const 定义数组常量
与 define() 类似,const 也可以定义存储数组的常量。
<?php
// 定义一个存储应用设置的数组常量
const APP_SETTINGS = [
'locale' => 'zh_CN',
'timezone' => 'Asia/Shanghai',
'items_per_page' => 20
];
echo '应用语言环境: ' . APP_SETTINGS['locale'] . '<br>';
echo '每页显示数量: ' . APP_SETTINGS['items_per_page'] . '<br>';
// 遍历数组常量
echo '应用设置列表:<br>';
foreach (APP_SETTINGS as $key => $value) {
echo '- ' . $key . ': ' . $value . '<br>';
}
?>3. define() 与 const 的区别
虽然 define() 和 const 都可以创建常量,但它们有几个关键的特性差异:
| 特性对比 | define() 函数 | const 关键字 |
|---|---|---|
| 定义时机 | 运行时 (可以在函数、循环内执行) | 编译时 (必须在顶层作用域) |
| 作用域 | 始终是全局的 | 全局,或者类级别 (后续讲解) |
| 大小写敏感 | 可以通过第三个参数设置为不敏感 (极不推荐) | 始终敏感 |
| 支持的值类型 | 标量、数组、资源 | 标量、数组、资源 |
| 表达式支持 | 支持表达式、函数调用等结果作为值 | 仅限简单的标量表达式 (PHP 5.6+) |
| 使用上下文 | 全局空间、函数内、if 条件语句内 | 全局空间、类/接口内部 |
最佳实践: 在现代 PHP 开发中,通常首推使用 const 来定义常量。因为它是编译时的,具有微小的性能优势,并且能强制实行更严格的常量定义规范。只有当你必须在条件语句、函数内部定义常量,或者常量的值需要由运行时的函数调用来决定时,才使用 define()。
4. 检查常量是否存在
你可以使用 defined() 函数来检查一个常量是否已经被定义。这在防止重复定义报错,或者在常量缺失时提供默认值时非常有用。
<?php
// 在使用或定义常量之前,先检查它是否存在
if (!defined('DB_PASS')) {
define('DB_PASS', 'secure_password');
}
echo '数据库密码: ' . DB_PASS . '<br>';
// 检查 APP_NAME 常量
if (defined('APP_NAME')) {
echo 'APP_NAME 已定义。<br>';
} else {
echo 'APP_NAME 未定义。<br>';
}
?>