Php 雄辩模型:防止瞬态(或“虚拟”属性保存到数据库

Php 雄辩模型:防止瞬态(或“虚拟”属性保存到数据库,php,eloquent,aggregate-functions,eloquent-relationship,transient,Php,Eloquent,Aggregate Functions,Eloquent Relationship,Transient,A有两个雄辩的模型相册和照片。相册可以包含更多的子相册或照片。因此,所有相册的集合是一个有向树。照片有一个属性take\u at,它存储拍摄照片时的时间戳 对于每个相册,我希望有两个“瞬态”或“虚拟”属性max_take_at和min_take_at,它递归地为相册及其子相册中的所有照片保留take_at的最小值和最大值。因此,它不像“代码>专辑:QueYES(->)-> Min(‘照片’,‘TakKayAt’)--WiMAX(‘照片’,‘TakayIt’’)/,因为这只会考虑相册中的直接儿童的

A有两个雄辩的模型
相册
照片
。相册可以包含更多的子相册或照片。因此,所有相册的集合是一个有向树。照片有一个属性
take\u at
,它存储拍摄照片时的时间戳

对于每个相册,我希望有两个“瞬态”或“虚拟”属性
max_take_at
min_take_at
,它递归地为相册及其子相册中的所有照片保留
take_at
的最小值和最大值。因此,它不像“代码>专辑:QueYES(->)-> Min(‘照片’,‘TakKayAt’)--WiMAX(‘照片’,‘TakayIt’’)/<代码>,因为这只会考虑相册中的直接儿童的照片,但我也想考虑间接的孩子。

还有两个要求:

  • 我希望
    Album::query()
    在默认情况下始终包含这些属性,而不需要记住任何复杂的构造
  • 出于效率考虑,
    max_take_at
    min_take_at
    的计算应直接在DB后端进行。我不希望Eloquent首先从DB中获取所有(直接和间接)子照片,然后在PHP中计算最小/最大值。这对于照片超过50k的大型安装是禁止的
我已经走了多远:

我利用Eloquent的作用域修改相册的默认查询,并将所需的属性包含到查询中,如下所示:

类相册扩展模型{
受保护的静态函数启动(){
父::booted();
//通常使用“范围”来限制查询结果
//通过添加额外的WHERE子句添加到特定子集
//返回到默认查询。
//但是,“作用域”可以用于以任何方式操纵查询。
//在这里,我们向查询中添加其他“虚拟”列。
静态::addGlobalScope('calc_minmax_take_at',函数(Builder$Builder){
$builder->addSelect([
'max_take_at'=>Photo::query()
->leftJoin(…)
//这里省略了复杂的SQL查询,以递归方式包含所有子相册中的照片
->订购人('take_at','desc')
->限制(1),
'min_take_at'=>Photo::query()
->leftJoin('albums as a'、'a.id'、'='、'album_id')
//这里省略了复杂的SQL查询,以递归方式包含所有子相册中的照片
->订购人('在'asc'处取得'U')
->限制(1),
]);
});
}
}
基本上,它类似于SQL视图,可以通过
create view
创建SQL视图,然后查询视图而不是表。结果正如预期的那样,而且速度很快(每个相册和子相册有50k张照片)