在 Eloquent 查询中使用 Laravel 模型方法

Using a Laravel model method in an Eloquent query

这是给 Laravel 5.2 的。我的用户模型中有一个定义如下的方法:

public function name()
{
    return "$this->name_first $this->name_last";
}

我正在尝试弄清楚如何将其用作查询的一部分,但由于一个显而易见的原因,这似乎是不可能的:数据库对该方法一无所知,这使得完美的感觉。然而,我试图实现的概念在某些情况下是有意义的,所以我想看看是否有一种方法可以在 Eloquent.

中自然地完成它

这行不通,但它代表了我正在努力实现的目标:

public function index(Request $request)
{
    $query = new User();

    if(Request::has('name')) {
        $query = $query->where('name', 'LIKE', '%' . Request::input('name') . '%');
    }

    return $query->get();
}

简而言之,数据库只知道 name_firstname_last,但我希望能够在 name 上搜索(和排序)而不存储它。也许存储串联名称没什么大不了的,我应该这样做,但我也在努力学习。

这意味着您应该在数据库级别连接列值。这意味着您可以使用 CONCAT and a whereRaw 子句:

$query->whereRaw('CONCAT(name_first, " ", name_last) LIKE ?', ['%' . Request::input('name') . '%']);

或者,如果您希望将全名 select 编辑为结果的一部分,您可以在 select 中连接并使用 having 而不是 where 以便能够使用列别名:

$query->select('*', DB::raw('CONCAT(name_first, " ", name_last) as name'))
      ->having('name', 'LIKE', '%' . Request::input('name') . '%');

不是最紧凑的解决方案,但涉及 MySQL 函数的事情需要一些原始 SQL 才能与查询生成器一起使用。

我同意 Bogdan 的观点,名字或姓氏中有空格的问题使得对各个列的查询变得困难,所以这可能是可行的方法。可以通过将其定义为自定义范围来增加代码重用: https://laravel.com/docs/5.2/eloquent#local-scopes

// class User
public function scopeOfFullNameLike($query, $fullName)
{
    return $query->whereRaw('CONCAT(name_first, " ", name_last) LIKE "%?%"', [$fullName]);
}
// ...
User::ofFullNameLike('john doe')->get();