Я думаю, что я нашел ошибку с setValue из ReflectionProperty - PullRequest
1 голос
/ 28 марта 2019

Я работаю над функцией рекурсивного удаления массивов и объектов. Проблема в том, что некоторые рекурсии могут находиться внутри частных свойств объектов.

ниже - это то, что я пробовал, а также записи, которые я пытался использовать.

это моя статья

class TestOBJ{

    private $fooClosure = null;
    public $bar = 5;
    private $myPrivateRecursion = null;
    private $aimArrayAndContainsRecursion = [];

    public function __construct()
    {
        $this->fooClosure = function(){
            echo 'pretty closure';
        };
    }

    public function setMyPrivateRecursion(&$obj){
        $this->myPrivateRecursion = &$obj;
    }

    public function setObjInsideArray(&$obj){
        $this->aimArrayAndContainsRecursion[] = &$obj;
    }
}

$std = new stdClass();
$std->std = 'any str';
$std->obj = new stdClass();
$std->obj->other = &$std;

$obj = new TestOBJ();
$obj->bar = new TestOBJ();
$obj->bar->bar = 'hey brow, please works';
$obj->bar->setMyPrivateRecursion($std);

моя заявка var $obj

и это моя функция / решение

function makeRecursionStack($vector, &$stack = [], $from = null)
{
    if ($vector) {
        if (is_object($vector) && !in_array($vector, $stack, true) && !is_callable($vector)) {
            $stack[] = &$vector;
            if (get_class($vector) === 'stdClass') {
                foreach ($vector as $key => $value) {
                    if (in_array($vector->{$key}, $stack, true)) {
                        $vector->{$key} = null;
                    } else {
                        $vector->{$key} = $this->makeRecursionStack($vector->{$key}, $stack, $key);
                    }
                }
                return $vector;
            } else {
                $object = new \ReflectionObject($vector);
                $reflection = new \ReflectionClass($vector);
                $properties = $reflection->getProperties();
                if ($properties) {
                    foreach ($properties as $property) {
                        $property = $object->getProperty($property->getName());
                        $property->setAccessible(true);
                        if (!is_callable($property->getValue($vector))) {
                            $private = false;
                            if ($property->isPrivate()) {
                                $property->setAccessible(true);
                                $private = true;
                            }

                            if (in_array($property->getValue($vector), $stack, true)) {
                                $property->setValue($vector, null);
                            } else {
                                //if($property->getName() === 'myPrivateRecursion' && $from === 'bar'){
                                //$get = $property->getValue($vector);
                                //$set = $this->makeRecursionStack($get, $stack, $property->getName());                                
                                //$property->setValue($vector, $set);
                                //pre_clear_buffer_die($property->getValue($vector));
                                //}
                                $property->setValue($vector, $this->makeRecursionStack($property->getValue($vector), $stack, $property->getName()));
                            }

                            if ($private) {
                                $property->setAccessible(false);
                            }
                        }
                    }
                }
                return $vector;
            }
        } else if (is_array($vector)) {
            $nvector = [];
            foreach ($vector as $key => $value) {
                $nvector[$key] = $this->makeRecursionStack($value, $stack, $key);
            }
            return $nvector;
        } else {
            if (is_object($vector) && !is_callable($vector)) {
                return null;
            }
        }
    }
    return $vector;
}

Там, где у меня есть комментарии, я заметил проблему. если If не прокомментировано, $get получит stdClass с рекурсией, и это прекрасно работает, а $set получит stdClass без рекурсии. В таком порядке.

$get =

$set =

После этой строки

$property->setValue($vector, $set);
pre_clear_buffer_die($property->getValue($vector));

я получаю это

Я пытаюсь указать другое значение, например, свойство bool или null, после установки $set, но оно не работает.

P.S: pre_clear_buffer_die убить php-буфер, инициализировать другой буфер и показать var внутри <pre> после выхода из скрипта. Это функция отладчика.

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