无法使用 :: 作用域运算符从实例访问类常量


Cannot access class constant from an instance using the :: scope operator

我今天遇到了一个奇怪的问题,即使作为一名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;
  }
}