Symfony项目同步关联关系时报Trying to get property 'sys_id' of non-object错误
问题原因
错误提示Notice: Trying to get property 'sys_id' of non-object说明你访问sys_id属性时,对应的变量不是合法的对象类型,常见原因有以下几种:
- 反序列化返回结构不匹配:你调用
synchronizeRelations方法返回的是RelationResultSnowDto实例,而非直接的RelationSnowDto数组。ServiceNow接口通常会把实际数据放在外层result字段中,如果你没有正确提取该字段就直接遍历$rels,遍历出来的$rel是外层Dto的属性值,而非关联对象。 $outbound_relations结构异常:你没有给出该变量的初始化逻辑,可能存在部分遍历项为null、数组或者其他非对象类型的情况。- 反序列化配置错误:Symfony序列化器未启用注解支持,导致
@SerializedName注解不生效,部分RelationSnowDto实例没有正确赋值sys_id属性,甚至反序列化失败返回非对象值。
排查步骤
- 先确认遍历的
$rel类型是否正确,在第一层循环开头添加类型检测:
foreach ($rels as $rel) { // 输出查看$rel的实际类型和值,同时确认$rels本身的结构 if (!$rel instanceof \App\Dto\Snow\Orga\Relation\RelationSnowDto) { var_dump($rel, $rels); die; } // 原有内层循环逻辑 }
- 再确认
$outbound_relation的类型,在内层循环开头添加检测:
foreach ($outbound_relations as $outbound_relation) { if (!is_object($outbound_relation) || !property_exists($outbound_relation, 'sys_id')) { var_dump($outbound_relation); die; } // 原有判断逻辑 }
- 检查
RelationResultSnowDto的定义,确认是否有声明类型为RelationSnowDto[]的公共$result属性,匹配ServiceNow接口的外层返回结构。
解决方案
如果确认是外层Dto结构的问题,修改代码提取实际的关联数组即可:
方案1:修改调用处代码
$relsDto = $this->synchronizeRelations(); // 提取外层Dto中的result字段,拿到实际的关联对象数组 $rels = $relsDto->result; foreach ($rels as $rel) { // 原有逻辑 }
方案2:修改同步方法直接返回数组
protected function synchronizeRelations() { $relation_list_raw = $this->snowTableApiClient->request('GET', 'cmdb_rel_ci', [ 'query' => [ 'sysparm_query' => 'type=60bc4e22c0a8010e01f074cbe6bd73c3^ORtype=1a9cb166f1571100a92eb60da2bce5c5^parent.sys_class_name=cmdb_ci_service^ORparent.sys_class_name=cmdb_ci_appl', 'sysparm_fields' => 'sys_id,parent,type,child', 'sysparm_limit' => 10 ] ]); $this->logger->info('Synchronize relations'); $resultDto = $this->serializer->deserialize( $relation_list_raw->getContent(), RelationResultSnowDto::class, 'json' ); // 直接返回关联数组,避免后续调用出错 return $resultDto->result; }
如果是反序列化配置的问题,确认Symfony序列化器已经启用了注解读取器,在config/packages/framework.yaml中添加如下配置:
framework: serializer: enable_annotations: true
如果存在部分数据为空的情况,可以在判断逻辑中添加空值防护:
if (is_object($rel) && is_object($outbound_relation) && $rel->sys_id === $outbound_relation->sys_id) { $servers[] = $this->businessServicesRelations($rel, $rels); break; }
内容的提问来源于stack exchange,提问作者Ewen
相关产品推荐
相关产品推荐

