类常量

可以在每个类基础上定义 常量,这些常量保持不变且不可修改。类常量的默认可见性是 public

注意:

子类可以重新定义类常量。从 PHP 8.1.0 开始,如果类常量被定义为 final,则子类无法重新定义它。

接口也可以有常量。查看 接口文档 以获取示例。

可以使用变量引用类。变量的值不能是关键字(例如 selfparentstatic)。

请注意,类常量是为每个类分配一次,而不是为每个类实例分配一次。

示例 #1 定义和使用常量

<?php
class MyClass
{
const
CONSTANT = 'constant value';

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

echo
MyClass::CONSTANT . "\n";

$classname = "MyClass";
echo
$classname::CONSTANT . "\n";

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

echo
$class::CONSTANT."\n";
?>

特殊的 ::class 常量允许在编译时解析完全限定的类名,这对于命名空间类很有用

示例 #2 命名空间 ::class 示例

<?php
namespace foo {
class
bar {
}

echo
bar::class; // foo\bar
}
?>

示例 #3 类常量表达式示例

<?php
const ONE = 1;
class
foo {
const
TWO = ONE * 2;
const
THREE = ONE + self::TWO;
const
SENTENCE = 'The value of THREE is '.self::THREE;
}
?>

示例 #4 类常量可见性修饰符,从 PHP 7.1.0 开始

<?php
class Foo {
public const
BAR = 'bar';
private const
BAZ = 'baz';
}
echo
Foo::BAR, PHP_EOL;
echo
Foo::BAZ, PHP_EOL;
?>

上述示例在 PHP 7.1 中的输出

bar

Fatal error: Uncaught Error: Cannot access private const Foo::BAZ in …

注意:

从 PHP 7.1.0 开始,类常量允许可见性修饰符。

添加注释

用户贡献的注释 12 notes

206
tmp dot 4 dot longoria at gmail dot com
13 年前
可以在基类中声明常量,并在子类中重写它,并且可以通过 'get_called_class' 方法从静态方法访问常量的正确值
<?php
abstract class dbObject
{
const
TABLE_NAME='undefined';

public static function
GetAll()
{
$c = get_called_class();
return
"SELECT * FROM `".$c::TABLE_NAME."`";
}
}

class
dbPerson extends dbObject
{
const
TABLE_NAME='persons';
}

class
dbAdmin extends dbPerson
{
const
TABLE_NAME='admins';
}

echo
dbPerson::GetAll()."<br>";//输出: "SELECT * FROM `persons`"
echo dbAdmin::GetAll()."<br>";//输出: "SELECT * FROM `admins`"

?>
144
kuzawinski dot marcin at gmail dot com
9 年前
从 PHP 5.6 开始,您终于可以使用数学表达式定义常量,例如这个

<?php

class MyTimer {
const
SEC_PER_DAY = 60 * 60 * 24;
}

?>

我很高兴 :)
151
匿名
13 年前
大多数人没有理解声明常量的意义,并在试图将函数或数组声明为常量时混淆了事情。接下来他们会尝试比必要更复杂的事情,有时会导致糟糕的编码习惯。让我解释一下...

常量是值的名称(但它不是变量),通常在代码编译时被替换,而不是在运行时。

因此,函数的返回值不能使用,因为它们只会在运行时返回值。

数组不能使用,因为它们是存在于运行时的数据结构。

声明常量的一个主要目的是在代码中使用值,可以在一个地方轻松替换,而无需查找所有出现的位置。另一个目的是避免错误。

考虑一些之前其他人编写的示例

1. const MY_ARR = "return array(\"A\", \"B\", \"C\", \"D\");";
有人说,这将声明一个可以使用 eval 的数组。错了!这只是一个常量字符串,而不是数组。如果可以将数组声明为常量,这有意义吗?可能没有。相反,将数组的值声明为常量,并创建一个数组变量。

2. const magic_quotes = (bool)get_magic_quotes_gpc();
当然,这行不通。也没有意义。该函数已经返回值,没有必要为相同的东西声明一个常量。

3. 有人谈到对常量的“动态”赋值。什么?常量没有动态赋值,运行时赋值只适用于变量。让我们看看提出的示例

<?php
/**
* 仅处理数据库的常量
*/
class DbConstant extends aClassConstant {
protected
$host = 'localhost';
protected
$user = 'user';
protected
$password = 'pass';
protected
$database = 'db';
protected
$time;
function
__construct() {
$this->time = time() + 1; // 动态赋值
}
}
?>

这些不是常量,而是类的属性。像“this->time = time()”这样的语句完全违背了常量的定义。常量应该像字面意思一样,在每次执行时保持不变。它们不应该随着脚本的每次运行或类的每次实例化而改变。

结论:不要试图将常量重新定义为变量。如果常量不起作用,直接使用变量即可。这样就不需要重新定义方法来实现现有功能。
116
delete dot this dot and dot dots dot gt at kani dot hu
10年前
我认为如果我们在这里强调一下延迟静态绑定,会很有帮助。
<?php
class A {
const
MY_CONST = false;
public function
my_const_self() {
return
self::MY_CONST;
}
public function
my_const_static() {
return static::
MY_CONST;
}
}

class
B extends A {
const
MY_CONST = true;
}

$b = new B();
echo
$b->my_const_self ? 'yes' : 'no'; // 输出: no
echo $b->my_const_static ? 'yes' : 'no'; // 输出: yes
?>
93
Xiong Chiamiov
10年前
const 也可以在命名空间中直接使用,这是文档中从未明确说明的功能。

<?php
# foo.php
namespace Foo;

const
BAR = 1;
?>

<?php
# bar.php
require 'foo.php';

var_dump(Foo\BAR); // => int(1)
?>
48
jimmmy dot chief at gmail dot com
7年前
您好,我想指出在扩展类中 self::CONST 和 $this::CONST 之间的区别。
让我们有一个类 a

<?php
class a {
const
CONST_INT = 10;

public function
getSelf(){
return
self::CONST_INT;
}

public function
getThis(){
return
$this::CONST_INT;
}
}
?>

和类 b(继承自 a)

<?php
class b extends a {
const
CONST_INT = 20;

public function
getSelf(){
return
parent::getSelf();
}

public function
getThis(){
return
parent::getThis();
}
}
?>

两个类都有同名常量 CONST_INT。
当子类调用父类中的方法时,使用 self 和 $this 的输出不同。

<?php
$b
= new b();

print_r($b->getSelf()); //10
print_r($b->getThis()); //20

?>
28
nepomuk at nepda dot de
8年前
[编辑注:从 PHP 5.6.0 开始,这已经是可行的。]

注意,从 PHP7 开始,可以使用数组定义类常量。

<?php
class MyClass
{
const
ABC = array('A', 'B', 'C');
const
A = '1';
const
B = '2';
const
C = '3';
const
NUMBERS = array(
self::A,
self::B,
self::C,
);
}
var_dump(MyClass::ABC);
var_dump(MyClass::NUMBERS);

// 结果:
/*
array(3) {
[0]=>
string(1) "A"
[1]=>
string(1) "B"
[2]=>
string(1) "C"
}
array(3) {
[0]=>
string(1) "1"
[1]=>
string(1) "2"
[2]=>
string(1) "3"
}
*/
?>
2
powtac at gmx dot de
1年前
由于描述中没有提到,以下类型可以设置为类常量:字符串、数组、整数、布尔值,可能还有浮点数。但不能是对象。

<?php

class Test {
const
arr = array();
const
string = 'string';
const
int = 99;
const
bool = true;
}

var_dump(
(new
Test())::arr,
(new
Test())::string,
(new
Test())::int,
(new
Test())::bool
);

/* PHP 7.0.0+ 的输出:

array(0) {
}
string(6) "string"
int(99)
bool(true)
8
wbcarts at juno dot com
15年前
使用 CONST 设置上限和下限

如果您有接受用户输入的代码,或者您只是需要确保输入是可接受的,可以使用常量来设置上限和下限。注意:强烈建议使用一个强制执行限制的静态函数... 以下的 clamp() 函数可以给您一个示例。

<?php

class Dimension
{
const
MIN = 0, MAX = 800;

public
$width, $height;

public function
__construct($w = 0, $h = 0){
$this->width = self::clamp($w);
$this->height = self::clamp($h);
}

public function
__toString(){
return
"Dimension [width=$this->width, height=$this->height]";
}

protected static function
clamp($value){
if(
$value < self::MIN) $value = self::MIN;
if(
$value > self::MAX) $value = self::MAX;
return
$value;
}
}

echo (new
Dimension()) . '<br>';
echo (new
Dimension(1500, 97)) . '<br>';
echo (new
Dimension(14, -20)) . '<br>';
echo (new
Dimension(240, 80)) . '<br>';

?>

- - - - - - - -
Dimension [width=0, height=0] - 默认大小
Dimension [width=800, height=97] - 宽度已被钳制到 MAX
Dimension [width=14, height=0] - 高度已被钳制到 MIN
Dimension [width=240, height=80] - 宽度和高度保持不变
- - - - - - - -

为您的类设置上限和下限也有助于您的对象变得更有意义。例如,Dimension 的宽度或高度不可能为负数。您有责任防止虚假输入破坏您的对象,并避免在代码的其他部分中出现潜在的错误和异常。
3
Paul
9 年前
通常可以使用方括号或花括号语法访问字符串中的单个字节(字符)。例如:$mystring[5]。但是,请注意,(出于某种原因)此语法不适用于字符串类常量(至少在 PHP 5.5.12 中不适用)。
例如,以下代码将给出“PHP Parse error: syntax error, unexpected '[' in php shell code on line 6”。
<?php
class SomeClass
{
const
SOME_STRING = '0123456790';
public static function
ATest()
{
return
self::SOME_STRING[0];
}
}
?>
看起来您必须使用变量/类成员。
2
Nimja
6 年前
请注意,此魔术常量不会加载类。事实上,它可以在不存在的类上工作。

这意味着它不会影响自动加载。

<?php
$className
= \Foo\Bar::class;
var_dump($className);
var_dump(class_exists($className, false));
?>

将输出

string(7) "Foo\Bar"
bool(false)
0
David Spector
5 年前
可以使用通常的逗号分隔语法来声明多个常量

class STATE
{
const INIT=0, NAME_SEEN=1, ADDR_SEEN=2;
}

这显示了声明一组枚举文字,适合在有限状态机循环中使用。使用“STATE::INIT”之类的语法引用此枚举。在这种情况下,它的实际类型将是整数。
To Top