php - 每次从数据库中检索模型集合后对其进行排序
问题描述
我有一个Product
和一个Tag
模型。它们以多对多关系连接。
当我得到一个集合时Tag
,我希望它随时被排序。因为排序算法是在 PHP 中实现的,所以我不能在数据库级别执行此操作。
我的第一次尝试是简单地覆盖newCollection()方法Model
:
// Tag.php
public function newCollection(array $models = []): Collection
{
return parent::newCollection($models)->sortBy(fn(Tag $tag) => $tag->present()->name)->values();
}
这样可行。不幸的是,从数据库中检索集合newCollection()
时总是调用两次:
第一次:Builder::hydrate()
第二次:Builder::get()Tag
这与高效相去甚远。于是我又做了一次尝试。newCollection()
我没有覆盖,而是覆盖了以下的newEloquentBuilder()方法Model
:
// Tag.php
public function newEloquentBuilder($query): Builder
{
return new class($query) extends Builder {
public function get($columns = ['*'])
{
return parent::get($columns)->sortBy(fn(Tag $tag) => $tag->present()->name)->values();
}
};
}
似乎工作!但不幸的是,不是每次。$product->tags
不会用Builder::get()
。它使用BelongsToMany::get()。
所以我的问题是:从数据库中检索到特定模型的集合后,是否有一种有效的方法来修改它?
解决方案
像这样修改默认行为通常是个坏主意,而且您经常会发现自己在某个地方需要原始默认行为。我认为更简洁的方法是向模型添加第二种方法,该方法检索集合然后应用排序方法。
public function sortedTags(): Collection {
return $this->tags->sortBy('tag.present.name');
}
您可能需要急切地加载关系以优化事物。
尽管如此,从性能的角度来看,这是一个坏主意。它加载所有数据,然后循环通过它进行排序。如果您可以将排序/排序推送到 sql 中,从长远来看,您会做得更好,特别是如果 Tags 表中的数据集预计会随着时间增长。它肯定会导致查询不太干净,因为您可能需要添加联接才能使事情正常工作,并且您可能希望根据复杂性切换到查询构建器。
推荐阅读
- html - 跨度和边界之间需要空间
- google-bigquery - 如何将过去几天的数据从 Firebase 重新加载到 BigQuery?
- jquery - 函数 close_window() { 如果
- ios - 启动时奇怪的 Facebook 崩溃
- c++ - 如何解决内存访问冲突异常
- xcode - Flutter Xcode:clang:错误:链接器命令失败,退出代码为 1(使用 -v 查看调用)
- c# - 如何在不知道密码的情况下使用 C# 检查项目的 TFS 2010 权限?
- jquery - 当我们点击时,如何在 4 后添加新的 div 导致 ngFor angular 5
- php - codeigniter hmvc 路由不适用于模块控制器,但可以在实时服务器上的 CI 默认控制器中找到
- c# - 如何更改禁用的 WPF 按钮的按钮样式?