Как получить значение свойства по ссылке, используя отражение в PHP? - PullRequest
2 голосов
/ 08 сентября 2011

Предположим, у вас есть класс, объявленный так:

class DummyObject{
    public $attr;
    public function __construct(){
        $this->attr=array('val_1','val_2','val_3');
    }
}

Делаем это:

$obj=(new DummyObject1());
$attr=&$obj->attr;

Вы получите ссылку на $attr, поэтому любые изменения, сделанные в массиве, будут выполнены также в экземпляре DummyObject $ obj.

И вот, наконец, вопрос. Используя отражение,, как я могу получить ссылку на массив, хранящийся в $attr, а не копию ?. Я попробовал это без успеха:

$obj=(new DummyObject());
$reflector = new ReflectionObject($obj);
$reflectorProperty = $reflector->getProperty('attr');
$propertyValue=$reflectorProperty->getValue($ref);

Фактически, $attr является копией исходного массива.

Заранее спасибо!

Ответы [ 3 ]

8 голосов
/ 10 июля 2013

Начиная с PHP 5.4 вы можете делать это без раздумий:

class Kitchen
{
    private $yummy = 'cake';
}

$reader = function & ($object, $property) {
    $value = & Closure::bind(function & () use ($property) {
        return $this->$property;
    }, $object, $object)->__invoke();

    return $value;
};

$kitchen = new Kitchen();
$cake    = & $reader($kitchen, 'yummy');
$cake    = 'sorry, I ate it!';

var_dump($kitchen);

Это благодаря способности PHP 5.4 переключать область замыкания во время выполнения.

Работающий пример можно найти на http://3v4l.org/sZMt1

Я на самом деле подробно объяснил технику и возможные варианты использования на http://ocramius.github.io/blog/accessing-private-php-class-members-without-reflection/

1 голос
/ 08 сентября 2011

Боюсь, ты не сможешь. ReflectionProperty::getValue должен был бы вернуться по ссылке, чтобы это было возможно, а это не так.

0 голосов
/ 30 апреля 2013

Вы можете получить его из исходного $ obj, который вы можете передать обратному вызову, с помощью оператора «use»

$propertyValue = $obj->{$reflectorProperty->getName()};

Или, если вы используете общедоступные методы получения / установки для частных пользователей, вы можете

$propertyName = $reflectorProperty->getName();
$methodName = 'get' . ucfirst($propertyName);
if (method_exists($obj, $methodName)) {
    $propertyValue = call_user_func([ $object, $methodName ]);
} elseif (isset($obj->{$propertyName}) {
    $propertyValue = $this->{$propertyName};
} else {
    $propertyValue = null;
}

Другое решение состоит в том, чтобы определить закрытый (или публичный) метод $ obj-> getProperty ($ name) и вызывать его из вашего обратного вызова через отражение и setAccessible.Как только этот метод определен в исходном классе, он получает доступ ко всем закрытым членам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...