Skip to content

PHP 类常量

概述

类常量(Class Constants)是在类中定义的不可变值。与属性不同,常量一旦定义就不能修改。类常量为每个类分配一次,而非每个实例。

版本要求

  • PHP 7.1+:常量支持访问修饰符
  • PHP 8.1+:支持 final 常量
  • PHP 8.3+:支持类型化类常量、动态获取常量、严格的接口可见性检查

基础概念

基本声明

使用 const 关键字声明类常量,默认可见性为 public

php
<?php
declare(strict_types=1);

class HttpStatusCode
{
    public const OK = 200;
    public const NOT_FOUND = 404;
    public const INTERNAL_ERROR = 500;
}

echo HttpStatusCode::OK; // 200

访问方式

类常量通过 ::(范围解析操作符)访问,支持多种方式。

php
<?php
declare(strict_types=1);

class MyClass
{
    public const CONSTANT = 'constant value';

    public function showConstant(): void
    {
        echo self::CONSTANT . "\n";
    }
}

// 类外部使用 ClassName::
echo MyClass::CONSTANT . "\n";

// 通过变量动态调用
$className = 'MyClass';
echo $className::CONSTANT . "\n";

// 通过对象实例
$obj = new MyClass();
echo $obj::CONSTANT . "\n";
$obj->showConstant();

语法与代码

访问修饰符(PHP 7.1+)

类常量支持 publicprotectedprivate 修饰符。

php
<?php
declare(strict_types=1);

class ApiConfig
{
    public const API_VERSION = 'v2';
    protected const MAX_RETRIES = 3;
    private const API_KEY = 'secret-key-123';

    public function getRetries(): int
    {
        return self::MAX_RETRIES;
    }

    public function getKey(): string
    {
        return self::API_KEY;
    }
}

$config = new ApiConfig();
echo ApiConfig::API_VERSION;  // v2
echo $config->getRetries();    // 3

// Error: Cannot access protected/private const
// echo ApiConfig::MAX_RETRIES;

final 常量(PHP 8.1+)

final 常量不能被子类重新定义。

php
<?php
declare(strict_types=1);

class BaseService
{
    final public const VERSION = '1.0';
    public const TIMEOUT = 30;
}

class UserService extends BaseService
{
    // Error: Cannot override final constant
    // public const VERSION = '2.0';

    public const TIMEOUT = 60; // 非 final 常量可以覆盖
}

echo UserService::TIMEOUT; // 60

类型化类常量(PHP 8.3+)

类常量可指定标量类型或数组类型,数组内容只能包含标量类型。

php
<?php
declare(strict_types=1);

class ServerConfig
{
    public const bool DEBUG = false;
    public const int PORT = 8080;
    public const float VERSION = 2.1;
    public const string HOST = 'localhost';
    public const array ALLOWED_IPS = ['127.0.0.1', '::1'];
}

var_dump(ServerConfig::DEBUG);  // bool(false)
var_dump(ServerConfig::PORT);   // int(8080)
var_dump(ServerConfig::VERSION); // float(2.1)
var_dump(ServerConfig::HOST);  // string(8) "localhost"

动态获取常量(PHP 8.3+)

使用变量名动态获取类常量。

php
<?php
declare(strict_types=1);

class Status
{
    public const PENDING = 'pending';
    public const ACTIVE = 'active';
    public const ARCHIVED = 'archived';
}

$name = 'ACTIVE';
echo Status::{$name}; // active

常量表达式

常量值可以是常量表达式,包括其他常量、数学运算等。

php
<?php
declare(strict_types=1);

class MathConstants
{
    public const PI = 3.14159;
    public const TAU = self::PI * 2;
    public const MAX_VALUE = 100;
    public const MIN_VALUE = 0;
    public const RANGE = self::MAX_VALUE - self::MIN_VALUE;
}

详细说明

接口中的常量可见性(PHP 8.3+)

PHP 8.3 起严格检查接口与实现类中常量的可见性一致性。

php
<?php
declare(strict_types=1);

interface CacheInterface
{
    public const DEFAULT_TTL = 3600;
}

class RedisCache implements CacheInterface
{
    // PHP 8.3+ Fatal error: 可见性必须为 public
    // protected const DEFAULT_TTL = 7200;

    public const DEFAULT_TTL = 7200; // 正确:保持 public
}

类常量 vs 静态属性

特性类常量静态属性
关键字conststatic
可变性不可变可变
默认值常量表达式常量表达式
类型声明PHP 8.3+PHP 7.4+
继承可覆盖(除非 final)可覆盖
适用场景配置、状态码计数器、缓存

实战示例

状态机模式

php
<?php
declare(strict_types=1);

class OrderStatus
{
    public const PENDING = 'pending';
    public const PAID = 'paid';
    public const SHIPPED = 'shipped';
    public const DELIVERED = 'delivered';
    public const CANCELLED = 'cancelled';

    public const array TRANSITIONS = [
        self::PENDING   => [self::PAID, self::CANCELLED],
        self::PAID      => [self::SHIPPED, self::CANCELLED],
        self::SHIPPED   => [self::DELIVERED],
        self::DELIVERED => [],
        self::CANCELLED => [],
    ];

    public static function canTransition(string $from, string $to): bool
    {
        return in_array($to, self::TRANSITIONS[$from] ?? [], true);
    }
}

var_dump(OrderStatus::canTransition('pending', 'paid')); // true
var_dump(OrderStatus::canTransition('pending', 'shipped')); // false

注意事项

  1. 常量名建议全大写:遵循 UPPER_SNAKE_CASE 命名规范
  2. 接口常量自动为 public:不能声明为 private 或 protected
  3. PHP 8.3 可见性检查更严格:实现接口时必须保持常量可见性一致
  4. self:: vs static::self:: 引用定义时的类,static:: 引用运行时的类

最佳实践

  • 配置值用常量:如超时时间、最大重试次数、API 版本等
  • 状态码/枚举值用常量:避免魔术字符串/数字
  • final 常量防止覆盖:对关键常量使用 final 修饰
  • PHP 8.3+ 使用类型化常量:获得额外的类型安全保障

进阶用法

调试与测试技巧

php
<?php
declare(strict_types=1);

// 单元测试辅助函数
function createTestResource(): mixed
{
    return match (true) {
        default => new stdClass(),
    };
}

// 调试输出函数
function debugOutput(mixed , string  = ''): void
{
     =  ? ": " : '';
     .= print_r(, true);
    fwrite(STDERR,  . "\n");
}

// 性能基准测试
function benchmark(callable , int  = 1000): float
{
     = hrtime(true);
    for ($i = 0; $i < $iterations; $i++) {
        $fn();
    }
    return (hrtime(true) - $start) / 1e9;
}

日志记录实践

php
<?php
declare(strict_types=1);

/**
 * 简易日志记录器
 */
class SimpleLogger
{
    private string $logFile;
    private string $level = 'INFO';

    public function __construct(string $logFile)
    {
        $this->logFile = $logFile;
    }

    public function info(string $message, array $context = []): void
    {
        $this->log('INFO', $message, $context);
    }

    public function warning(string $message, array $context = []): void
    {
        $this->log('WARNING', $message, $context);
    }

    public function error(string $message, array $context = []): void
    {
        $this->log('ERROR', $message, $context);
    }

    private function log(string $level, string $message, array $context): void
    {
        $timestamp = date('Y-m-d H:i:s');
        $contextStr = $context ? ' ' . json_encode($context, JSON_UNESCAPED_UNICODE) : '';
        $line = "[{$timestamp}] [{$level}] {$message}{$contextStr}\n";
        file_put_contents($this->logFile, $line, FILE_APPEND | LOCK_EX);
    }
}

配置与环境检测

php
<?php
declare(strict_types=1);

// 环境检测工具
class EnvironmentChecker
{
    public static function checkRequirements(array $requirements): array
    {
        $results = [];
        foreach ($requirements as $name => $check) {
            $results[$name] = is_callable($check) ? $check() : false;
        }
        return $results;
    }

    public static function getSystemInfo(): array
    {
        return [
            'php_version' => PHP_VERSION,
            'os' => PHP_OS,
            'sapi' => PHP_SAPI,
            'memory_limit' => ini_get('memory_limit'),
            'max_execution_time' => ini_get('max_execution_time'),
            'loaded_extensions' => get_loaded_extensions(),
        ];
    }
}

常见问题排查

问题可能原因解决方案
连接超时网络问题/配置错误检查配置,增加超时时间
权限不足文件/目录权限使用 chmod/chown 修正
性能下降索引缺失/数据量大添加索引,优化查询
数据不一致并发冲突/事务残留使用锁机制和事务
内存溢出大数据集/未释放资源增大内存限制,分批处理

故障排除步骤

  1. 检查错误日志和异常信息
  2. 确认配置和环境是否正确
  3. 使用调试工具逐步排查
  4. 参考官方文档查找已知问题

版本兼容性说明

功能最低版本说明
基础功能PHP 8.1本文档基准版本
只读属性PHP 8.1public readonly 修饰符
枚举类型PHP 8.1enum 类型和 match 表达式
FiberPHP 8.1协程/轻量级并发
命名参数PHP 8.0foo(arg_name: value)
联合类型PHP 8.0`int
Null 安全运算符PHP 8.0$obj?->method()
析构器 promotionPHP 8.0__construct(public $x)
php
<?php
declare(strict_types=1);

// 版本兼容性检测
function ensureVersion(string $minVersion): void
{
    if (version_compare(PHP_VERSION, $minVersion, '<')) {
        throw new RuntimeException(
            sprintf('需要 PHP %s+, 当前版本: %s', $minVersion, PHP_VERSION)
        );
    }
}

ensureVersion('8.1.0');

参考链接