首页 > 解决方案 > Laravel 雄辩的查询使用带有条件语句和参数的本地范围

问题描述

我在我的 Car 模型中编写了以下函数,它执行以下操作:

  1. 根据两个日期(接送/下车)获取相关预订
  2. 检查这些预订的数量是否等于或超过汽车的数量
  3. 最后根据输出返回一个布尔值
   /**
    * Custom Functions
    */

   public function isAvailableFor($from, $to) {
       $reservationsCount = $this->reservations->where('pickup_date', '>=', $from)->where('dropoff_date', '<=', $to)->count();
       if($reservationsCount >= $this->quantity) {
           return false;
       }
       return true;
   }

该功能按预期工作,但我想使用本地范围以更优雅的方式实现它,因此我可以在控制器中查询 Car 模型时有效地使用它,但我找不到正确的方法和我的代码变得一团糟。

例如,我只需键入以下范围即可使用Car::active()->get();

    /**
     * Scopes
     */
    public function scopeActive($query)
    {
        return $query->where('status', 'active');
    }

主要问题是该count()功能不允许我以范围方式实现我的功能,或者至少我没有提出解决方案的经验。提前致谢。

更新

正如 OsDev 正确指出的那样,因为我的函数返回一个布尔值,所以它不能直接在作用域函数中实现。我也可以在我的作用域函数中执行此操作,但我想这有点矫枉过正:

    public function scopeAvailable($query, $from, $to) {
        $excludedId = array();
        $cars = Car::whereHas('reservations')->get();
        foreach($cars as $car) {
            if(!$car->isAvailableFor($from, $to)) {
                array_push($excludedId, $car->id);
            }
        }
        return $query->whereNotIn('id', $excludedId);
    }

标签: phpmysqllaraveleloquent

解决方案


您必须返回$query计数结果,因为这样您就不会破坏 Query Builder 链

您不能组合作用域和模型函数,因为作用域应该返回$query构建器对象,在该示例中,您的函数返回一个布尔值。

你可以做这样的事情

  /**
     * Scopes
     */
    public function scopeIsAvailableFor($query,$from,$to)
    {
        return $query->where('pickup_date', '>=', $from)->where('dropoff_date', '<=', $to);
    }

然后你可以链接它并调用 count 如果你想

$count = Car::active()->isAvailableFor('2020-05-03','2020-05-06')->count();

也许您可以将新范围包装到模型方法中

public function isAvailableFor($from, $to) {

    $reservationsCount = $this->reservations->isAvailableFor($from,$to)->count();

    return !$reservationsCount >= $this->quantity;

   }

推荐阅读