PHP常量详解:从入门到进阶(小白友好版)

63 阅读3分钟

PHP常量详解:从入门到进阶(小白友好版)


一、常量基础概念

1. 什么是常量?

常量是不可变的值,一旦定义就不能被修改。常量通常用于存储固定不变的数据(如配置项、数学常数等)。


二、常量的定义方式

PHP提供两种定义常量的方式:

1. const 关键字(推荐)

const PI = 3.14; // 必须在最顶端作用域定义

注意

  • const 必须写在全局作用域类内部
  • 不能在函数/循环/条件语句中使用
// ❌ 错误示例(在函数中定义):
function test() {
    const ERROR = 'Invalid'; // 报错
}

2. define() 函数

define('MAX_ATTEMPTS', 3); // 可以在任何地方定义

对比表格

特性constdefine()
定义位置必须在顶层作用域可以在任何位置
是否支持可见性✅(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

十、练习题

  1. 如何访问全局常量 ERROR_CODE
    👉 echo \ERROR_CODE;

  2. 为什么下面代码会报错?

    function test() {
        const MAX = 100; // ❌ 报错
    }
    

    👉 const 不能在函数内部定义

  3. 子类如何访问父类的常量?
    👉 parent::NAMEParentClass::NAME