PHP常量详解:从入门到进阶(小白友好版)
一、常量基础概念
1. 什么是常量?
常量是不可变的值,一旦定义就不能被修改。常量通常用于存储固定不变的数据(如配置项、数学常数等)。
二、常量的定义方式
PHP提供两种定义常量的方式:
1. const 关键字(推荐)
const PI = 3.14; // 必须在最顶端作用域定义
注意:
const必须写在全局作用域或类内部- 不能在函数/循环/条件语句中使用
// ❌ 错误示例(在函数中定义):
function test() {
const ERROR = 'Invalid'; // 报错
}
2. define() 函数
define('MAX_ATTEMPTS', 3); // 可以在任何地方定义
对比表格:
| 特性 | const | define() |
|---|---|---|
| 定义位置 | 必须在顶层作用域 | 可以在任何位置 |
| 是否支持可见性 | ✅(public/private) | ❌ 不支持 |
| 是否支持表达式 | ❌ 必须是字面量 | ✅ 支持表达式 |
| 性能 | 略快(编译时定义) | 稍慢(运行时定义) |
三、常量的作用域规则
1. 全局常量 vs 命名空间常量
// 全局常量(公共文件)
define('NAME', 'dzl');
// 命名空间中的常量
namespace app\controller;
define('NAME', 'wlj');
访问规则:
echo NAME; // 输出 wlj(当前命名空间的常量)
echo \NAME; // 输出 dzl(全局常量)
echo constant('app\controller\NAME'); // 输出 wlj
echo constant('\NAME'); // 输出 dzl
2. 类常量 vs 全局常量
class Test {
const NAME = 'dzl';
}
class Study extends Test {
const NAME = 'wlj';
public function show() {
echo self::NAME; // 输出 wlj(当前类的常量)
echo parent::NAME; // 输出 dzl(父类的常量)
echo Test::NAME; // 输出 dzl(直接访问父类)
}
}
四、重要注意事项
1. 常量不可变性
define('MAX', 10);
MAX = 20; // ❌ 致命错误:Cannot reassign constant value
2. 常量名称规则
- 常量名区分大小写(不建议)
- 命名建议:全大写 + 下划线分隔(如
MAX_VALUE)
3. 判断常量是否存在
if (defined('DEBUG_MODE')) {
// 常量已定义
}
五、命名空间常量的完整路径
| 写法 | 实际访问的常量 |
|---|---|
NAME | 当前命名空间的 NAME |
\NAME | 全局命名空间的 NAME |
\app\controller\NAME | 指定命名空间的 NAME |
六、PHP预定义常量
1. PHP版本相关
echo PHP_VERSION; // 如 8.2.1
echo PHP_MAJOR_VERSION; // 8
echo PHP_MINOR_VERSION; // 2
2. 魔术常量(自动解析)
echo __FILE__; // 当前文件完整路径
echo __LINE__; // 当前行号
echo __DIR__; // 当前文件所在目录
echo __CLASS__; // 当前类名(带命名空间)
echo __FUNCTION__; // 当前函数名
echo __METHOD__; // 当前方法名(类名::方法名)
echo __NAMESPACE__; // 当前命名空间
示例:
namespace app\controller;
class Test {
public function index() {
echo __NAMESPACE__; // 输出 app\controller
echo __METHOD__; // 输出 app\controller\Test::index
}
}
七、常见错误与解决方案
1. 重复定义常量
define('NAME', 'dzl');
define('NAME', 'wlj'); // ❌ 致命错误:Cannot redeclare constant
解决方法:
if (!defined('NAME')) {
define('NAME', 'dzl');
}
2. 命名空间中找不到常量
namespace app\controller;
define('NAME', 'wlj');
echo \NAME; // ❌ 报错:常量 NAME 未定义
正确访问方式:
echo \app\controller\NAME; // ✅ 输出 wlj
八、最佳实践
| 场景 | 推荐做法 |
|---|---|
| 配置参数 | 使用命名空间常量(define()) |
| 类相关常量 | 使用 const 并设置为 public |
| 动态值 | 使用变量或静态属性 |
| 避免冲突 | 使用 defined() 判断后再定义 |
| 项目规范 | 常量名统一全大写 + 下划线分隔 |
九、总结
| 常量类型 | 定义方式 | 作用域 | 是否可变 | 访问方式 |
|---|---|---|---|---|
| 全局常量 | define() | 全局作用域 | ❌ | NAME 或 \NAME |
| 命名空间常量 | define() | 指定命名空间 | ❌ | \Ns\NAME |
| 类常量 | const | 类作用域 | ❌ | Class::NAME |
| 静态属性 | static $var | 类作用域 | ✅ | Class::$var |
十、练习题
-
如何访问全局常量
ERROR_CODE?
👉echo \ERROR_CODE; -
为什么下面代码会报错?
function test() { const MAX = 100; // ❌ 报错 }👉
const不能在函数内部定义 -
子类如何访问父类的常量?
👉parent::NAME或ParentClass::NAME