Laravel 4.2老旧应用修改hasMany关联为从API取数据报错如何解决
问题原因
你遇到的两个报错核心逻辑是一致的:Laravel 4.2中,当你以动态属性$rep->credits的形式访问credits()方法时,Laravel会默认将该方法识别为Eloquent关系方法,强制要求返回Illuminate\Database\Eloquent\Relations\Relation类型的对象,用于后续自动执行关联查询。
- 第一次直接返回API数组不符合类型要求,抛出关系类型错误
- 第二次把API返回的数据集传入
hasMany(),但hasMany()第一个参数要求传入Eloquent模型类名,而非实际数据集,因此抛出查询方法不存在的错误
最优解决方案(无需修改Blade模板)
用Eloquent访问器替换原有关系方法,返回Laravel 4.2原生支持的Collection对象,完全兼容原有模板的sum()调用逻辑,不需要改动任何Blade代码:
class Rep extends \Eloquent { // 缓存API请求结果,避免同一请求内多次访问重复调用API protected $cachedCredits = null; // 新增访问器,对应动态属性$rep->credits public function getCreditsAttribute() { // 命中缓存直接返回 if (!is_null($this->cachedCredits)) { return $this->cachedCredits; } $searchParam = [ "apiId" => 7438, "data" => [ "RepNumber" => $this->attributes['id'], ] ]; $result = (new ApiCallerController)->apiSearch($searchParam); $apiData = $result['data']; // 将API返回的数组转为Collection对象,原生支持sum()方法 $this->cachedCredits = \Illuminate\Support\Collection::make($apiData); return $this->cachedCredits; } }
修改完成后,原有模板代码{{round($rep->credits->sum('Credits'), 2)}}可以直接正常运行,无需调整。
备选方案(可修改模板时使用)
如果不介意调整模板调用代码,也可以直接把credits()改为普通方法,模板调用时加上括号即可:
- 模型代码保持你原有修改逻辑,只需在最后把API数组转为Collection:
public function credits() { $searchParam = [ "apiId" => 7438, "data" => [ "RepNumber" => $this->attributes['id'], ] ]; $result = (new ApiCallerController)->apiSearch($searchParam); return \Illuminate\Support\Collection::make($result['data']); }
- 模板调用改为:
{{round($rep->credits()->sum('Credits'), 2)}}
内容的提问来源于stack exchange,提问作者Lance
相关产品推荐
相关产品推荐

