Laravel Resource使用when实现条件资源项时报非对象属性获取错误
为什么Laravel Resource的
when写法会触发报错 核心原因拆解
$this->when()是Laravel Api Resource内置的条件输出方法,它的参数执行逻辑和你手写的三目运算完全不一样,直接照搬三目的传参写法必然会出问题。- 首先要搞懂PHP方法传参的基础规则:所有写在方法参数位置的表达式,都会在方法被调用前即时计算出结果,再传入方法内部。
你写的$this->when($this->recup, $this->recup->test)这行,在真正进入when方法执行逻辑前,PHP就已经把第二个参数$this->recup->test算完了——不管第一个判断条件是不是为真,代码都会硬闯去读取$this->recup的test属性。如果这时候recup关联没有匹配到对应记录(值为null),就已经触发了非对象取属性的报错,根本轮不到when方法帮你做条件判断。 - 你看到的具体报错
Trying to get property 'value' of non-object,来源也和上面的传参逻辑直接相关:你提前算好传入的第二个参数值,会被when方法默认当成Resource响应实例处理——当判断条件为真时,when内部会尝试读取这个传入对象的value属性来组装响应。但你传进去的是普通的模型属性值、甚至是关联模型实例,根本不是Resource实例,没有value属性,自然就触发了这个报错。
为什么手写的三目运算可以正常运行
你写的$this->recup ? ($this->recup->test) : 'null'是典型的短路求值逻辑:
- 代码会先判断
$this->recup是不是有值 - 只有当判断结果为真的时候,才会执行后面的
$this->recup->test读取属性 - 如果
$this->recup是null,代码直接返回'null',根本不会触发对非对象取属性的操作
这和when方法提前计算所有参数值的逻辑完全不同,所以手写三目可以稳定运行。
正确的when方法写法
when方法的设计初衷,就是让你把条件满足时要返回的内容、默认返回的内容,用无参闭包传进去,让Laravel在内部判断完条件之后,再去执行闭包里的代码读取对应值,从根源上避免提前求值的问题:
// 正确写法 'te' => $this->when( $this->recup, // 条件为真时才会执行这个闭包,读取对应属性 fn () => $this->recup->test, // 条件为假时的默认值,同样可以包成闭包 fn () => 'null' ),
这样写之后:
- 传入
when的只是几个闭包对象,PHP不会提前执行闭包里的代码 - 等
when内部判断完$this->recup确实有值的时候,才会调用对应闭包读取属性,不会出现对null取属性的问题 - 因为闭包返回的是普通的属性值,不是Resource实例,
when内部也不会尝试读取不存在的value属性,报错自然就消失了。
内容的提问来源于stack exchange,提问作者Larave
相关产品推荐
相关产品推荐

