10

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

最后一个例子更像我正在做和经历的......

4

6 回答 6

16

只需将实例变量与范围解析运算符一起使用:

$a = new a();
var_dump($a::abc);

打印 1

于 2012-08-15T20:37:19.140 回答
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+ 以后实现,考虑到我们最终有数组取消引用,我们可能会要求他们尽快添加静态取消引用。

于 2012-08-15T20:54:39.913 回答
4

PHP 文档指出类常量是通过 SRO( ::) 而不是->.

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

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

echo MyClass::constant . "\n";
于 2012-08-15T20:39:01.080 回答
3

就像我提到的,在 php 中,常量与类定义相关联,它们根据定义是静态的,不能使用 -> 运算符访问。

如果你真的想在你的编码范式中使用它,你可以试试 php5 中的反射类。

class MyClass
{
   const A = "I am A";
}

$o = new ReflectionClass( "MyClass" );
echo $o->getconstant("A"); //will print "I am A"

另外,我认为您的EDIT中的示例可能不起作用..我没有运行它,但我不确定是否可以在任何非类引用上调用 SRO(::) ..

于 2012-08-15T22:07:40.223 回答
2

我知道这是一个旧线程,但是对于想知道最好的方法的人来说,看看 PHP 函数constant()

使用 constant() 你可以简单地做到这一点:

$a = new a();
$value = constant(get_class($a)."::abc");
// $value === 1

这从 PHP 4 开始可用,并且在 PHP 5.5 中仍然可以完美运行

于 2013-11-05T18:17:23.070 回答
-1

当尝试使用const在不同命名空间内的类中定义时,可以使用范围解析运算符::)而不会出现问题,正如文档所述,在使用这种格式声明 const 的类之​​前为命名空间添加前缀:

  • (<namespace>"\")*<className>::<const>

使用下一个命名空间、类和 const 定义:

模型/OperationModel.php

<?php
namespace models;

class OperationModel {
  const OPERATION_INITIALIZING = 1;
}

您可以像这样使用另一个命名空间\类中的 const:

控制器/MobileController.php

<?php
namespace controllers;

use models\OpertionModel;

class MobileController {
  private function thingy() {
    $operation_status = models\OperationModel::OPERATION_INITIALIZING;
  }
}
于 2018-10-10T20:58:38.470 回答