Laravel 8中getCasts重复调用致性能下降,求优化方案
Laravel 8中CompanyRounds模型getCasts()高频调用的性能优化方案
针对查询363条CompanyRounds数据时getCasts()被调用5904次导致的性能问题,结合你依赖casts和appends的业务需求,提供以下优化方案:
1. 缓存casts计算结果到模型实例
默认getCasts()每次调用都会合并父类casts并重新计算,重写该方法将结果缓存到实例属性,每个模型实例仅计算一次:
protected $cachedCasts; public function getCasts() { if (!isset($this->cachedCasts)) { $this->cachedCasts = parent::getCasts(); } return $this->cachedCasts; }
2. 按需加载appends字段
避免全局加载所有appends,根据业务场景动态控制:
- 查询时临时禁用不必要的appends,后续手动添加需要的字段:
$rounds = CompanyRounds::withoutAppends()->get(); // 仅对需要的模型实例添加特定appends字段 foreach ($rounds as $round) { $round->append(['funding_amount', 'investor_count']); } - 定义查询作用域,只加载业务必需的appends:
public function scopeWithCoreAppends($query) { return $query->setAppends(['funding_amount', 'investor_count']); } // 使用时 $rounds = CompanyRounds::withCoreAppends()->get();
3. 转换为数组后处理数据
将模型集合转为数组,一次性处理casts和appends,后续操作数组避免反复触发模型方法:
// 先转换为数组,减少模型属性访问次数 $roundsArray = CompanyRounds::get()->toArray(); foreach ($roundsArray as $round) { // 直接操作数组元素,不再触发getCasts() $processedData[] = [ 'id' => $round['id'], 'funding_amount' => $round['funding_amount'], 'investor_list' => $round['investor_list'] ]; }
4. 优化属性访问逻辑
减少循环中对模型属性的重复访问,使用only()方法批量获取所需属性:
$processedData = CompanyRounds::get()->map(function ($round) { // 一次性获取需要的属性集合 return $round->only(['id', 'funding_amount', 'investor_count']); });
5. 应用Laravel 8最新补丁
Laravel 8的后续补丁版本对模型casts的缓存逻辑有优化,升级到同版本的最新补丁包,可直接享受框架层面的性能提升。
内容的提问来源于stack exchange,提问作者vok7777
相关产品推荐
相关产品推荐

