我想我从ReflectionProperty找到了setValue的错误

时间:2019-03-28 12:47:53

标签: php recursion reflection

我正在研究一个函数以递归方式删除数组和对象。问题在于某些递归可能位于对象的私有属性中。

下面是我尝试过的以及尝试使用的条目。

这是我的入口

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缓冲区,初始化其他缓冲区,并在退出脚本后在<pre>中显示var。是调试器功能。

0 个答案:

没有答案