PHP支持递归引用,但会导致序列化时产生错误.

$arr=array(1,2);
// 递归引用自己
$arr['c']=&$arr;

class A{
    public $self;
    public function __construct(){
// 引用自身
        $this->self=$this;
    }
}
$obj=new A;

var_dump($arr,$obj);

各版本出输

PHP8.1:

array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  ["c"]=>
  *RECURSION*
}
object(A)#1 (1) {
  ["self"]=>
  *RECURSION*
}

Result for 7.4.30, 7.1.33, 5.3.29:

array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  ["c"]=>
  &array(3) {
    [0]=>
    int(1)
    [1]=>
    int(2)
    ["c"]=>
    *RECURSION*
  }
}
object(A)#1 (1) {
  ["self"]=>
  *RECURSION*
}

Result for 5.1.6:

array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  ["c"]=>
  &array(3) {
    [0]=>
    int(1)
    [1]=>
    int(2)
    ["c"]=>
    &array(3) {
      [0]=>
      int(1)
      [1]=>
      int(2)
      ["c"]=>
      *RECURSION*
    }
  }
}
object(A)#1 (1) {
  ["self"]=>
  object(A)#1 (1) {
    ["self"]=>
    *RECURSION*
  }
}

var_export

会产生warning错误.
把循环引用改成null;不能正常反序列化.

Result for 8.1.9, 7.4.30, 7.1.33:

Warning: var_export does not handle circular references in /home/user/scripts/code.php on line 14
array (
  0 => 1,
  1 => 2,
  'c' => NULL,
)
Warning: var_export does not handle circular references in /home/user/scripts/code.php on line 15
A::__set_state(array(
   'self' => NULL,
))

Result for 5.3.29:

Fatal error: Nesting level too deep - recursive dependency? in /home/user/scripts/code.php on line 14

Result for 5.1.6:

array (
  0 => 1,
  1 => 2,
  'c' => 
  array (
    0 => 1,
    1 => 2,
    'c' => 
    array (
      0 => 1,
      1 => 2,
      'c' => 
      array (
        0 => 1,
        1 => 2,
        'c' => 
        array (

json_encode

会产生错误,输出false;
报Recursion detected 错误.

echo json_encode($arr);
echo json_last_error_msg();

echo json_encode($obj);
echo json_last_error_msg();

-w1287

serialize

都能正常序列化和反序列化.

-w1273

-w1291

处理循环引用

常用框架的忽略json错误.

$data=[1,2,3];
$data['self']=&$data;
// 原生
json_encode($data);// 无错误
json_last_error_msg()// Recursion detected
return json_encode($data,JSON_PARTIAL_OUTPUT_ON_ERROR); // self=>null

// laravel 
return $data; // 严重错误
return response($data,200);// 严重错误
return new JsonResponse($obj, 200, [], JSON_PARTIAL_OUTPUT_ON_ERROR);// self=>null

// phalcon
$serialize=new Phalcon\Storage\Serializer\Php($data);
echo $serialize->serialize();//允许

$serialize=new Phalcon\Storage\Serializer\Json($data);
echo $serialize->serialize();//严重错误

$Response=new \Phalcon\Http\Response();
$Response->setJsonContent($data,JSON_PARTIAL_OUTPUT_ON_ERROR);// BUG,参数不生效
$Response->send();

// hyperf
return $data; // 严重错误
return $response->json($data);// 严重错误,不支持json参数
return Json::encode($data,JSON_PARTIAL_OUTPUT_ON_ERROR);// self=>null

-w885

原作者:阿金
本文地址:https://hi-arkin.com/archives/php-recusion.html

标签: php recusion

(本篇完)

评论