加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

php – 在JsonSerializable中编码克隆$this

发布时间:2020-12-13 16:06:21 所属栏目:PHP教程 来源:网络整理
导读:这种简化的情况导致 PHP段错误(退出127): class Datum implements JsonSerializable{ public function jsonSerialize(){ return clone $this; }}echo json_encode(new Datum); 最后一行代码导致退出(127).我无法在当前环境中检索任何堆栈. 同时,删除克隆令
这种简化的情况导致 PHP段错误(退出127):

class Datum implements JsonSerializable{
  public function jsonSerialize(){
    return clone $this;
  }
}
echo json_encode(new Datum);

最后一行代码导致退出(127).我无法在当前环境中检索任何堆栈.

同时,删除克隆令牌的工作原理.

有没有可能的解释为什么会发生这种情况?

解决方法

此代码导致无限递归.

看来PHP JSON模块以这种方式支持JsonSerializable(伪代码):

function json_encode($data){
    if($data instanceof JsonSerializable) return json_encode($data->jsonSerialize());
    else real_json_encode($data); // handling primitive data or arrays or pure data objects
}

如果你返回另一个JsonSerializable实例,json_encode将尝试再次序列化它,导致无限递归.

这适用于返回$this;但是,可能是由于json_encode实现的故意解决方法,当返回的对象相同时,即返回$this时,它直接转到真实的json_encode.但是,由于$a!== clone $a,因此克隆对象不会发生这种情况.

参考

这个答案可以通过php-src的引用来支持.

// in php_json_encode_zval
if (instanceof_function(Z_OBJCE_P(val),php_json_serializable_ce)) {
    return php_json_encode_serializable_object(buf,val,options,encoder);
}

// in php_json_encode_serializable_object
if ((Z_TYPE(retval) == IS_OBJECT) &&
    (Z_OBJ(retval) == Z_OBJ_P(val))) {
    /* Handle the case where jsonSerialize does: return $this; by going straight to encode array */
    PHP_JSON_HASH_APPLY_PROTECTION_DEC(myht);
    return_code = php_json_encode_array(buf,&retval,encoder);
} else {
    /* All other types,encode as normal */
    return_code = php_json_encode_zval(buf,encoder);
    PHP_JSON_HASH_APPLY_PROTECTION_DEC(myht);
}

这些片段证明PHP会编码返回$this;作为一个数组(或作为一个不可序列化的对象),返回任何其他东西使得Z_OBJ(retval)== Z_OBJ_P(val)为false,转到另一个块,再次递归调用php_json_encode_zval.

TL; DR,简单解决方案:return(array)$this;而不是克隆$this;.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读