PHP 常量详解

常量是 PHP 中用于存储固定值的标识符,一旦定义就不能被修改或取消定义。常量在整个脚本中都是全局可用的。

什么是常量?

常量是一个简单值的标识符(名称),在脚本执行期间该值不能改变。常量默认区分大小写,按照惯例常量标识符总是大写的。

常量的特点:

  • 值在定义后不能被改变
  • 默认全局作用域
  • 名称通常使用大写字母
  • 只能包含标量数据(boolean、integer、float、string)
  • 在定义时不需要 $ 符号

定义常量

PHP 中有两种定义常量的方法:使用 define() 函数和使用 const 关键字。

使用 define() 函数

define() 函数语法

define(string $name, mixed $value, bool $case_insensitive = false): bool

define() 函数示例

<?php
// 定义常量
define("SITE_NAME", "ab教程网");
define("VERSION", "1.0.0");
define("MAX_USERS", 1000);
define("IS_ACTIVE", true);
define("PI", 3.14159265359);

// 使用常量
echo "网站名称: " . SITE_NAME . "<br>";
echo "版本: " . VERSION . "<br>";
echo "最大用户数: " . MAX_USERS . "<br>";
echo "圆周率: " . PI . "<br>";

// 检查常量是否定义
if (defined("SITE_NAME")) {
    echo "SITE_NAME 常量已定义<br>";
}

// 不区分大小写的常量(不推荐使用)
define("GREETING", "Hello World", true);
echo greeting;  // 输出: Hello World
?>

使用 const 关键字

const 关键字示例

<?php
// 使用 const 定义常量
const DB_HOST = "localhost";
const DB_USER = "root";
const DB_PASS = "password";
const DB_NAME = "my_database";

// 在类中定义常量
class Config {
    const MAX_FILE_SIZE = 5242880; // 5MB
    const ALLOWED_TYPES = ['jpg', 'png', 'gif'];
    const DEFAULT_TIMEZONE = 'Asia/Shanghai';
}

// 使用类常量
echo "最大文件大小: " . Config::MAX_FILE_SIZE . " bytes<br>";
echo "默认时区: " . Config::DEFAULT_TIMEZONE . "<br>";

// 在条件语句中使用 const(PHP 5.6+)
if (true) {
    const DYNAMIC_CONST = "动态定义"; // PHP 5.3+ 允许
}
?>

define() 与 const 的区别

特性 define() const
定义位置 可以在任何地方定义 必须在最外层作用域或类中定义
条件定义 支持在条件语句中定义 PHP 5.6+ 支持条件定义
值类型 可以是任何表达式 只能是标量值(PHP 5.6+ 支持数组)
命名空间 受命名空间影响 受命名空间影响
性能 运行时定义 编译时定义,稍快
大小写敏感 可设置为不敏感 始终敏感

最佳实践: 对于简单的标量值,推荐使用 const,因为它在编译时处理,性能稍好。对于需要在运行时计算的表达式或条件定义,使用 define()

魔术常量

PHP 提供了一系列魔术常量,它们的值会根据使用的上下文而变化。

魔术常量示例

<?php
// 魔术常量示例
echo "当前行号: " . __LINE__ . "<br>";
echo "当前文件: " . __FILE__ . "<br>";
echo "当前目录: " . __DIR__ . "<br>";

function testFunction() {
    echo "当前函数: " . __FUNCTION__ . "<br>";
    echo "当前类: " . __CLASS__ . "<br>";
    echo "当前方法: " . __METHOD__ . "<br>";
    echo "当前命名空间: " . __NAMESPACE__ . "<br>";
}

class TestClass {
    public function showInfo() {
        echo "当前类: " . __CLASS__ . "<br>";
        echo "当前方法: " . __METHOD__ . "<br>";
        echo "当前命名空间: " . __NAMESPACE__ . "<br>";
    }
}

testFunction();
$obj = new TestClass();
$obj->showInfo();

// PHP 8.0+ 的特性
echo "当前特征: " . __TRAIT__ . "<br>";
?>

__LINE__

文件中的当前行号

__FILE__

文件的完整路径和文件名

__DIR__

文件所在的目录

__FUNCTION__

函数名称

__CLASS__

类的名称

__METHOD__

类的方法名

__NAMESPACE__

当前命名空间的名称

__TRAIT__

Trait 的名称(PHP 5.4+)

预定义常量

PHP 提供了许多预定义常量,可以在任何脚本中使用。

常用预定义常量

<?php
// PHP 版本信息
echo "PHP 版本: " . PHP_VERSION . "<br>";
echo "PHP 主版本: " . PHP_MAJOR_VERSION . "<br>";
echo "PHP 次版本: " . PHP_MINOR_VERSION . "<br>";
echo "PHP 发布版本: " . PHP_RELEASE_VERSION . "<br>";

// 操作系统信息
echo "操作系统: " . PHP_OS . "<br>";
echo "目录分隔符: " . DIRECTORY_SEPARATOR . "<br>";
echo "路径分隔符: " . PATH_SEPARATOR . "<br>";

// 错误报告级别
echo "最大整数值: " . PHP_INT_MAX . "<br>";
echo "最小整数值: " . PHP_INT_MIN . "<br>";
echo "整数大小: " . PHP_INT_SIZE . " bytes<br>";

// 浮点数精度
echo "浮点数精度: " . PHP_FLOAT_DIG . "<br>";
echo "浮点数最大值: " . PHP_FLOAT_MAX . "<br>";
echo "浮点数最小值: " . PHP_FLOAT_MIN . "<br>";

// 行结束符
echo "行结束符: " . PHP_EOL;

// 显示所有预定义常量
// print_r(get_defined_constants(true));
?>

常量作用域

常量默认具有全局作用域,可以在整个脚本的任何地方访问。

常量作用域示例

<?php
define("GLOBAL_CONST", "我是全局常量");

function testScope() {
    // 在函数内部访问全局常量
    echo "在函数内部: " . GLOBAL_CONST . "<br>";

    // 在函数内部定义常量
    define("FUNCTION_CONST", "函数内定义的常量");
}

testScope();

// 在函数外部访问函数内定义的常量
echo "在函数外部: " . FUNCTION_CONST . "<br>";

// 类常量作用域
class MyClass {
    const CLASS_CONST = "类常量";

    public function showConstant() {
        // 在类方法内部访问类常量
        echo "在类方法中: " . self::CLASS_CONST . "<br>";

        // 访问全局常量
        echo "全局常量: " . GLOBAL_CONST . "<br>";
    }
}

$obj = new MyClass();
$obj->showConstant();

// 在类外部访问类常量
echo "类外部访问: " . MyClass::CLASS_CONST . "<br>";
?>

PHP 7+ 常量数组

从 PHP 5.6 开始,可以使用 const 定义数组常量,PHP 7 进一步增强了这一特性。

数组常量示例

<?php
// PHP 5.6+ 使用 const 定义数组常量
const CONFIG = [
    'database' => [
        'host' => 'localhost',
        'user' => 'root',
        'pass' => 'password'
    ],
    'settings' => [
        'debug' => true,
        'cache' => false
    ]
];

// 访问数组常量
echo "数据库主机: " . CONFIG['database']['host'] . "<br>";
echo "调试模式: " . (CONFIG['settings']['debug'] ? '开启' : '关闭') . "<br>";

// PHP 7+ 使用 define() 定义数组常量
define('ANIMALS', [
    'dog',
    'cat',
    'bird'
]);

echo "第一个动物: " . ANIMALS[0] . "<br>";

// 在类中定义数组常量
class Settings {
    const PERMISSIONS = [
        'admin' => ['read', 'write', 'delete'],
        'user' => ['read', 'write'],
        'guest' => ['read']
    ];
}

echo "管理员权限: " . implode(', ', Settings::PERMISSIONS['admin']) . "<br>";
?>

常量相关函数

PHP 提供了一些用于操作和检查常量的函数。

常量函数示例

<?php
// 定义一些常量
define("APP_NAME", "My Application");
define("APP_VERSION", "2.0.1");
const MAX_USERS = 100;

// 检查常量是否定义
if (defined("APP_NAME")) {
    echo "APP_NAME 已定义<br>";
}

// 获取所有已定义的常量
$constants = get_defined_constants(true);
echo "用户定义常量数量: " . count($constants['user']) . "<br>";

// 检查常量名称是否有效
$constant_name = "APP_NAME";
if (preg_match('/^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$/', $constant_name)) {
    echo "{$constant_name} 是有效的常量名<br>";
}

// 使用 constant() 函数通过字符串获取常量值
$value = constant("APP_NAME");
echo "通过 constant() 获取: " . $value . "<br>";

// 动态定义常量
$dynamic_const_name = "DYNAMIC_CONST";
define($dynamic_const_name, "动态定义的常量");
echo constant($dynamic_const_name) . "<br>";
?>

常量的最佳实践

命名规范

良好的命名示例

<?php
// 推荐的命名方式(全大写,下划线分隔)
define("DATABASE_HOST", "localhost");
define("MAX_FILE_UPLOAD_SIZE", 5242880);
define("DEFAULT_USER_ROLE", "subscriber");

// 在类中使用
class Config {
    const SITE_TITLE = "我的网站";
    const ADMIN_EMAIL = "admin@example.com";
    const CACHE_DURATION = 3600;
}

// 不推荐的命名方式
define("dbHost", "localhost");      // 不符合命名规范
define("maxSize", 1000);           // 不够清晰
?>

组织和管理常量

常量配置文件示例

<?php
// config.php - 常量配置文件

// 数据库配置
define("DB_CONFIG", [
    'host' => 'localhost',
    'name' => 'myapp_db',
    'user' => 'app_user',
    'pass' => 'secure_password',
    'charset' => 'utf8mb4'
]);

// 应用配置
define("APP_CONFIG", [
    'debug' => true,
    'environment' => 'development',
    'timezone' => 'Asia/Shanghai',
    'locale' => 'zh_CN'
]);

// 路径配置
define("ROOT_PATH", dirname(__DIR__));
define("UPLOAD_PATH", ROOT_PATH . '/uploads');
define("LOG_PATH", ROOT_PATH . '/logs');

// 在应用中使用
echo "数据库主机: " . DB_CONFIG['host'] . "<br>";
echo "根路径: " . ROOT_PATH . "<br>";
echo "环境: " . APP_CONFIG['environment'] . "<br>";
?>

常量与变量的区别

特性 常量 变量
定义方式 define() 或 const $ 符号直接赋值
值可变性 定义后不能改变 可以随时改变
作用域 全局作用域 有局部和全局作用域
数据类型 只能是标量值或数组 可以是任何类型
命名规范 通常全大写 通常小写或驼峰式
性能 编译时处理 运行时处理

总结

  • 常量用于存储不会改变的值,使用 define()const 定义
  • 常量默认全局可用,名称通常使用大写字母
  • 魔术常量提供上下文相关的信息
  • PHP 提供了许多预定义常量用于获取系统信息
  • 从 PHP 5.6 开始支持数组常量
  • 使用适当的命名规范和组织方式来管理常量
  • 常量在编译时处理,性能优于变量