在PHP中的匿名函数中访问对象的私有/受保护属性

5
我想通过匿名函数来转储对象的私有属性元素。当然,我可以用许多其他方法来实现这一点,但这凸显了一个 PHP 难题,我无法脱口而出解决它,除非是使用 $foo = $this 并使用 $foo - 但那不会给我私有的东西,那么... 有什么建议吗?
示例代码:
class MyClass
{
    private $payload = Array( 'a' => 'A element', 'b' => 'B element');

    static $csvOrder = Array('b','a');

    public function toCSV(){
        $values = array_map(
            function($name) use ($this) { return $this->payload[$name]; },  
            self::$csvOrder
        );
        return implode(',',$values);
    }
}

$mc = new MyClass();
print $mc->toCSV();

1
这是"从闭包中访问私有变量"的副本,但NikiC的答案适用于访问非公共方法和非公共属性,因此不投票支持闭包。 - outis
3个回答

3

我相信直接实现你提出的内容是不可能的。

然而,你可以通过将匿名方法作为类方法(这不是你要求的,但这可能是一个实际的解决方案),或者显式地从$this中提取需要的所有内容并将提取的值传递到函数中来解决它:

class MyClass
{
    private $payload = Array( 'a' => 'A element', 'b' => 'B element');

    static $csvOrder = Array('b','a');

    public function toCSV(){
        $payload = $this->payload;
        $values = array_map(
            function($name) use ($payload) { return $payload[$name]; },  
            self::$csvOrder
        );
        return implode(',',$values);
    }
}

确实 - 你的代码反映了我在这个特定情况下要做的事情。好吧,总的来说,这是一个有趣的问题 - 希望有一种方法可以解决我不知道的问题。谢谢你的回答 :) - Wagemage
+1 我之前已经发布了一个包含这个答案的回复,但我没有意识到你已经说过了。最简单的解决方案通常是最好的。 - Andrew Curioso

3
您可以通过创建一个使用反射的包装器来绕过限制,以便您可以访问所有属性和方法。然后,您可以像这样使用它:
$self = new FullAccessWrapper($this);
function () use ($self) { /* ... */ }

以下是一个包装器的示例实现,取自这里:

class FullAccessWrapper
{
    protected $_self;
    protected $_refl;

    public function __construct($self)
    {
        $this->_self = $self;
        $this->_refl = new ReflectionObject($self);
    }

    public function __call($method, $args)
    {
        $mrefl = $this->_refl->getMethod($method);
        $mrefl->setAccessible(true);
        return $mrefl->invokeArgs($this->_self, $args);
    }

    public function __set($name, $value)
    {
        $prefl = $this->_refl->getProperty($name);
        $prefl->setAccessible(true);
        $prefl->setValue($this->_self, $value);
    }

    public function __get($name)
    {
        $prefl = $this->_refl->getProperty($name);
        $prefl->setAccessible(true);
        return $prefl->getValue($this->_self);
    }

    public function __isset($name)
    {
        $value = $this->__get($name);
        return isset($value);
    }
}

显然,上述实现并未涵盖所有方面(例如,它无法使用魔术属性和方法)。

有趣的邪恶 :) 当然,这可能不是我在生产中要做的事情,但它确实解决了问题 - 谢谢。 - Wagemage

1

就像您自己所说,这是私有的因此无法访问。

您可以:

  • 将 $this->payload 作为参数传递给匿名函数。
  • 在类中创建一个方法并使用它代替。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接