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

在PHP的匿名函数中访问对象的私有/受保护属性,php,oop,anonymous-function,Php,Oop,Anonymous Function,我试图通过一个匿名函数转储对象私有属性的元素-当然我可以通过其他任何方式实现这一点,但这突出了一个PHP难题,我无法马上解决,除了$foo=$this和使用$foo-但这不会给我私有的东西,所以。。。建议 示例代码: class MyClass { private $payload = Array( 'a' => 'A element', 'b' => 'B element'); static $csvOrder = Array('b','a'); pub

我试图通过一个匿名函数转储对象私有属性的元素-当然我可以通过其他任何方式实现这一点,但这突出了一个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();

我相信绝对没有办法直接执行你的建议

但是,您可以通过使匿名方法成为类方法(这不是您所要求的,但可能是一个实用的解决方案)或显式地从
$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);
    }
}

正如你自己所说的,它是私人的,因此是可访问的

你可以:

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

您可以通过创建一个利用反射的包装器来绕过这个限制,允许您访问所有属性和方法。您可以这样使用它:

$self = new FullAccessWrapper($this);
function () use ($self) { /* ... */ }
下面是包装器的示例实现,取自:


显然,上面的实现并没有涵盖所有方面(例如,它不能使用神奇的属性和方法)。

事实上,您的代码反映了我在这种特殊情况下所做的事情。哦,总的来说,这是一个有趣的问题——我希望有办法解决我根本不知道的问题。谢谢你的回答:)+1在我意识到你已经说过这句话之前,我贴了一个答案。最简单的解决方案往往是最好的。有趣的是,邪恶:)当然可能不是我为生产所做的,但它确实解决了问题-谢谢,但NikiC的答案适用于访问非公共方法以及非公共属性,因此不投票赞成关闭。
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);
    }
}