我今天遇到了一个奇怪的问题,即使作为一名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);
最后一个例子更像我正在做的和体验...
答案 0 :(得分:13)
答案 1 :(得分:9)
我找到了一种相对简洁的方法来让我的问题更容易生活。这是我应用的解决方案。它不一定是最好的,但对于我的用途,它完全符合我的需要。
通过创建一个魔法__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以后发生,考虑到我们最终有阵列解除引用,我们可能会要求他们尽快添加静态解除引用。
答案 2 :(得分:4)
The PHP documentation表示通过SRO(::
)而不是->
访问类常量。
<?php
class MyClass
{
const constant = 'constant value';
function showConstant() {
echo self::constant . "\n";
}
}
echo MyClass::constant . "\n";
答案 3 :(得分:2)
如果您真的想在编码范例中使用它,可以在php5中尝试反射类。
class MyClass
{
const A = "I am A";
}
$o = new ReflectionClass( "MyClass" );
echo $o->getconstant("A"); //will print "I am A"
另外,我认为 EDIT 中的示例可能无法正常工作..我没有运行它,但我不确定是否可以在任何不能运行的东西上调用SRO(::)一个班级参考..
答案 4 :(得分:2)
我知道这是一个旧线程,但对于想要了解最佳方法的人来说,请查看PHP函数constant()。
使用constant(),您只需执行此操作:
$a = new a();
$value = constant(get_class($a)."::abc");
// $value === 1
自PHP 4开始提供此功能,并且仍可在PHP 5.5中完美运行
答案 5 :(得分:0)
尝试使用在不同命名空间中的类中定义的const
时,可以使用范围解析运算符(::
),而不会出现{{3 }}在声明const的类之前使用以下格式在名称空间前添加前缀:
(<namespace>"\")*<className>::<const>
使用下一个名称空间,类和const定义:
models / OperationModel.php
<?php
namespace models;
class OperationModel {
const OPERATION_INITIALIZING = 1;
}
您可以像这样使用来自另一个命名空间\类的const:
controllers / MobileController.php
<?php
namespace controllers;
use models\OpertionModel;
class MobileController {
private function thingy() {
$operation_status = models\OperationModel::OPERATION_INITIALIZING;
}
}