Доступ к закрытым / защищенным свойствам объекта в анонимной функции в PHP

Я пытаюсь сбрасывать элементы частной собственности объекта с помощью анонимной функции - конечно, я мог бы добиться этого любым количеством других способов, но это подчеркивает загадку 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();

person Wagemage    schedule 17.06.2011    source источник
comment
Дубликат Доступ к частным переменным из замыкания, но ответ NikiC работает как для доступа к закрытым, так и к закрытым методам. properties, поэтому не голосование за закрытие.   -  person outis    schedule 13.02.2012


Ответы (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);
    }
}
person Jon    schedule 17.06.2011
comment
Действительно - ваш код отражает то, чем я закончил в этом конкретном случае. Ну что ж, это вообще интересная проблема - я надеялся, что есть способ решить проблему, о которой я просто не знал. Спасибо за ответ :) - person Wagemage; 17.06.2011
comment
+1 Я отправил ответ с этим, прежде чем понял, что вы это уже сказали. Самое простое решение зачастую оказывается лучшим. - person Andrew Curioso; 17.06.2011

Вы можете обойти это ограничение, создав оболочку, которая использует Reflection, чтобы предоставить вам доступ ко всем свойствам и методам. Тогда вы можете использовать это так:

$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);
    }
}

Очевидно, что приведенная выше реализация не охватывает всех аспектов (например, она не может использовать магические свойства и методы).

person NikiC    schedule 17.06.2011
comment
Интересно зло :) Конечно, я бы не сделал этого для продакшена, но это действительно решает проблему - спасибо - person Wagemage; 17.06.2011

Как вы сами сказали, это личное и, следовательно, доступное.

Ты сможешь:

  • Передайте $ this-> payload в качестве параметра анонимной функции.
  • Создайте метод в классе и используйте его вместо него.
person Shay Ben Moshe    schedule 17.06.2011