雄辩的搜索/自定义属性的位置

NiR*_*iRR 11 laravel eloquent

我为我的模型添加了一个自定义属性

public function getTouchedAttribute() { ...
Run Code Online (Sandbox Code Playgroud)

我想将此添加到查询中

hasMany()->where('touched', ...)
Run Code Online (Sandbox Code Playgroud)

但显然这不是表中的一列.

实现这种行为的最优雅方式是什么?

luk*_*ter 9

一个选项(在性能方面可能是更好的选项)是使用原始SQL函数模拟属性.(不能帮助你,因为我不知道是什么touched)

另一种方法是filter在结果集合上使用:

$collection = Model::all();
$filtered = $collection->filter(function($model){
    return $model->touched == true;
});
Run Code Online (Sandbox Code Playgroud)


Uğu*_*ıcı 9

我知道这是一个已有 4 年历史的话题(从 2015 年开始),但它仍然从网络搜索中获得流量。所以我想分享一个想法;

您可以使用Eloquent 的本地查询范围来定义自定义 where 子句。

正如文档中所说:

本地范围允许您定义常见的约束集,您可以在整个应用程序中轻松地重复使用这些约束。例如,您可能需要经常检索所有被视为“热门”的用户。要定义范围,请为 Eloquent 模型方法添加范围前缀。

举个例子:如果您在模型上定义自定义范围:

public function scopePopular($query)
{
    return $query->where('votes', '>', 100);
}
Run Code Online (Sandbox Code Playgroud)

您可以直接将其与您的模型一起使用。

App\User::popular()->orderBy('created_at')->get();
Run Code Online (Sandbox Code Playgroud)

因此您可以定义一个scopeTouched()方法并实现您的逻辑。我假设如果updated_at不等于created_at,则此处会触及该行。当然你可以改变这种行为。

public function scopeTouched($query)
{
    return $query->where('updated_at', '!=', 'created_at');
}
Run Code Online (Sandbox Code Playgroud)

并将其与您的模型一起使用。

Model::touched()->get();
Run Code Online (Sandbox Code Playgroud)

当然,您可以将它与其他查询生成器方法一起使用。

Model::touched()->paginate(20);
Model::touched()->orderBy('id', 'DESC')->take(10)->get();
Model::touched()->latest()->first();
Run Code Online (Sandbox Code Playgroud)