Laravel 雄辩查询的高级 where

Posted

技术标签:

【中文标题】Laravel 雄辩查询的高级 where【英文标题】:Advanced where Laravel eloquent query 【发布时间】:2020-01-11 08:45:13 【问题描述】:

我目前被困在一个 where Laravel 查询上。问题是,我想根据给定表中的最新记录过滤一些数据。目前,我的查询如下所示:

$clients = $clients->whereDoesntHave('bill')->orWhereHas('bill', function ($query) use ($activeSchoolYear)
     $query
         ->where('created_at', '<', Carbon::parse($activeSchoolYear->start));
 )

$activeSchoolYear-&gt;start 是今天的日期。

如果我的 bills 表中有多个记录,就会出现问题。例如,如果我有两条不同日期的记录:

ID | Name  | created_at          |
1  | test  | 2019-09-09 15:31:25|
2  | test2 | 2018-09-10 16:42:44|

查询仍然返回两个日期,即使其中一个为假。我认为该查询会查找数据库中的所有记录,并且仍然返回给定的用户,因为其中一个日期是正确的。我的问题是,是否可以仅针对数据库中的最新行。或者这不能使用 eloquent 来完成。任何帮助表示赞赏。

编辑:

正如@Caddy 建议的那样,我使用了查询范围,但我对其进行了一些修改:

public function scopeNoActiveBill($query)
  return $query
            ->groupBy('created_at')->take(1)
            ->where('created_at', '<=', Carbon::create(2019, 9, 1));

我试图只从 bills 表中取出最后一行。然后,在控制器内部,这是我的查询:

$clients = $clients->whereDoesntHave('bill')
     ->orWhereHas('bill', function ($query) use ($activeSchoolYear)
            $query->noActiveBill();
      )
      ->whereHas('contracts', function ($query) use ($request) 
            $query
                  ->where('contract_type', '<', 2)
                  ->where('signed', 1)
                  ->where('school_year_id', $request['school_year']);
       );

因此,我希望既没有任何账单的客户,也希望有符合给定标准的账单的客户。如果客户只有一张账单,该查询可以正常工作,但问题是当客户有多个账单时。如果这些账单中的任何一个符合给定范围,它就会返回该账单。我只想检查最新的记录,如果该记录符合范围条件,则退回帐单。

编辑 2:

感谢@Caddy DZ 的asnwer,我设法得到了想要的结果。我只是更改了条件以监视在给定日期之前没有创建账单的客户。查询范围:

public function scopeNoActiveBill($query)
     return $query->where('created_at', '>=', Carbon::create(2019, 9, 1));

控制器:

$clients = $clients->whereDoesntHave('bill')
    ->orWhereDoesntHave('bill', function ($query) use ($activeSchoolYear)
        $query->noActiveBill();
    );

【问题讨论】:

目前您只过滤clients 而不是bills,为什么您希望只收到一张账单?你从哪里收到多张账单?当你打电话给$client-&gt;bills?您可以使用$client-&gt;bills()-&gt;latest()-&gt;first();获取客户的最新账单。 我试图从用户那里获得相关的账单。我不能只使用latest()-&gt;first(),因为我预计会有大约 203 个结果。 【参考方案1】:

你可以使用 Eloquent whereDate()。

->whereDate('created_at', '<', Carbon::parse($activeSchoolYear->start));

【讨论】:

你能给出你要比较的确切日期字符串吗?【参考方案2】:

您正在寻找的是这样的关系查询范围

$clients = App\Client::with(['bills' => function ($query) 
   $query->today();
])->get();

像这样将today() 范围添加到您的Bill 模型Bill.php

public function scopeToday($query)

    // Change today by $activeSchoolYear if necessary
    return $query->whereDate('created_at', '<', today());

假设Client 中的hasMany 关系

public function bills()

    return $this->hasMany(Bill::class);

像这样播种的数据DatabaseSeeder.php

// Will be returned because whereDoesntHave('bills')
$clientWithoutBills = Client::create([]);
$client = Client::create([]);
$client->bills()->createMany([
    [
        'name' => 'test',
        'created_at' => Carbon\Carbon::yesterday()
    ],
    [
        // Will not be returned because created today (not < today)
        'name' => 'test1'
    ],
    [
        // Will not be returned because created tomorrow
        'name' => 'test2',
        'created_at' => Carbon\Carbon::tomorrow()
    ]
]);

Results

[
    
        "id": 1,
        "created_at": "2019-09-09 16:20:24",
        "updated_at": "2019-09-09 16:20:24",
        "bills": []
    ,
    
        "id": 2,
        "created_at": "2019-09-09 16:20:24",
        "updated_at": "2019-09-09 16:20:24",
        "bills": [
            
                "id": 1,
                "name": "test",
                "client_id": 2,
                "created_at": "2019-09-08 00:00:00",
                "updated_at": "2019-09-09 16:20:24"
            
        ]
    
]

希望对你有帮助

【讨论】:

感谢您的详尽回复。我试着用你的罐头稍作修改,但我仍然收到一些不在规定范围内的客户账单。我将尝试使用您的解决方案,如果设法获得所需的结果,我会告诉您。 您可以编辑您的问题并添加您期望的结果示例吗?很难猜出你真正想要什么 对不起,我花了这么长时间才回复。我只想在 bills 表中的最后一行使用 where 子句。如果该行符合给定条件,则返回它,否则不返回任何内容。就我而言,如果我有 4 行,而第一行不符合条件,它仍然会返回该账单,因为其他 3 行符合给定条件。我稍微编辑了我的问题 更新:设法做到了,但我稍微改变了逻辑。我在查询范围内使用了whereDoesntHave 函数,以查看在给定日期之后创建的账单。将您的答案标记为已接受,因为它帮助我解决了这个问题。再次感谢。 很高兴它有帮助!

以上是关于Laravel 雄辩查询的高级 where的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 雄辩的极限查询

带有雄辩查询的 Laravel 分页

laravel 雄辩的关系查询

Laravel 5 雄辩的查询混淆

Laravel 4 雄辩的查询

Laravel:自我 JOIN 的雄辩查询