我今天遇到了一个奇怪的问题,即使作为一名PHP工程师,我也对此感到困惑:
似乎您可以从对象实例访问类常量,例如:
class a {
const abc = 1;
}
$a = new a();
var_dump($a->abc);
这将输出 null 而不是预期的 1。我能够做到以下几点:
class a {
const abc = 1;
}
$a = new a();
var_dump(a::abc);
但是在一个并不真正知道父对象到底是谁的子对象的上下文中,我发现这样做非常烦人:
class a {
const abc = 1;
}
$a = new a();
$c = get_class($a);
var_dump($c::abc);
是我还是这完全愚蠢,如果不是,请告诉我为什么它以这种方式工作。
编辑
另一种方法,但它并不是更好:
class a {
const abc = 1;
}
class b {
public function getA(){
return new a();
}
}
$b = new b();
$c = $b->getA();
var_dump($c::abc);
最后一个例子更像是我正在做的事情和经历......
只需将实例变量与范围解析运算符一起使用:
$a = new a();
var_dump($a::abc);
这将打印1
.
我找到了一种相对漂亮和干净的方法,让我的问题更容易接受。这是我应用的解决方案。它不一定是最好的,但对于我的使用来说,它完全符合我的需求。
通过创建一个魔术__get方法,我从实例的角度截获对常量名称的请求,并使用快速反射来查看该常量是否存在并返回其值。
这允许我实际上在一行中使用如下所示的模式:
class a {
const abc = 1;
public function __get($key){
$r = new ReflectionObject($this);
if($r->hasConstant($key)){ return $r->getConstant($key); }
}
}
class b {
public function getA(){
return new a();
}
}
$b = new b();
var_dump($b->getA()->abc);
var_dump($b->getA()->def);
虽然我想做:
var_dump($b->getA()::abc);
var_dump($b->getA()::def);
我想这在 5.4+ 的后期可能是可能的,考虑到我们最终有数组取消引用,我们可能会要求他们尽快添加静态取消引用。
PHP 文档指出类常量是通过 SRO (::
) 而不是 ->
访问的。
<?php
class MyClass
{
const constant = 'constant value';
function showConstant() {
echo self::constant . "'n";
}
}
echo MyClass::constant . "'n";
ike 我提到的,在 php 中,常量与类定义相关联,它们根据定义是静态的,无法使用 -> 运算符访问。
如果你真的想在你的编码范式中使用它,你可以尝试 php5 中的反射类。
class MyClass
{
const A = "I am A";
}
$o = new ReflectionClass( "MyClass" );
echo $o->getconstant("A"); //will print "I am A"
另外,我认为您的编辑中的示例可能不起作用。我没有运行它,但我不确定 SRO(::)可以在任何不是类引用的内容上调用。
这是一个古老的线程,但是对于想知道最佳方法的人,请查看PHP函数constant()。
使用 constant(),您可以简单地执行此操作:
$a = new a();
$value = constant(get_class($a)."::abc");
// $value === 1
这从 PHP 4 开始就可用,并且在 PHP 5.5 中仍然完美运行
当尝试使用在不同命名空间内的类中定义的const
时,可以使用范围解析运算符 ( ::
) 可以毫无问题地使用,如在声明 const 的类之前前缀命名空间的文档中所述:
-
(<namespace>"'")*<className>::<const>
使用下一个命名空间、类和常量定义:
模型/运营模型.php
<?php
namespace models;
class OperationModel {
const OPERATION_INITIALIZING = 1;
}
你可以使用另一个命名空间''类中的 const,如下所示:
控制器/移动控制器.php
<?php
namespace controllers;
use models'OpertionModel;
class MobileController {
private function thingy() {
$operation_status = models'OperationModel::OPERATION_INITIALIZING;
}
}