Eloquent有没有办法只得到()匹配的结果?

时间:2017-03-22 21:45:45

标签: laravel laravel-5 eloquent

我有以下功能

public function index(Request $request)
  {
    $results = Service::whereHas('conditions', function ($query) use ($request){
      $query->whereIn('id', $request->conditions);
    })
    ->whereHas('locations', function ($query) use ($request){

      $ran = false;
      foreach($request->locations as $location)
      {
        if(!$ran)
        {
          $query->Where('town', 'like', '%'.$location.'%')
          ->orWhere('city', 'like', '%'.$location.'%');
        }
        else
        {
          $query->orWhere('town', 'like', '%'.$location.'%')
          ->orWhere('city', 'like', '%'.$location.'%');
        }
        $ran = true;
      }
    })
    ->with('types', 'contacts', 'locations.datetimes')->toSql();

    dd($results);
  }

产生

select * from `services` where exists 
  (select * from `conditions` inner join `condition_service` on `conditions`.`id` = `condition_service`.`condition_id` where `services`.`id` = `condition_service`.`service_id` and `id` in (13, 14) and `conditions`.`deleted_at` is null) 
and exists 
  (select * from `service_locations` inner join `service_location_service` on `service_locations`.`id` = `service_location_service`.`service_location_id` where `services`.`id` = `service_location_service`.`service_id` and 
    (`town` like 'manchester' or `city` like 'manchester' or `town` like 'crewe' or `city` like 'crewe') 
  and `service_locations`.`deleted_at` is null) and `services`.`deleted_at` is null

问题是位置上的whereHas会带回所有结果,而我只想要城镇/城市匹配的结果。什么是实现这一目标的最佳方式?

2 个答案:

答案 0 :(得分:1)

我认为您需要使用回调对您的位置查询进行分组,该回调将查询包装在()中,然后直接处理第一个位置,将其从数组中删除并迭代循环。所以下面的代码应该适用于你的情况。

    $results = Service::whereHas('conditions', function ($query) use ($request){
      $query->whereIn('id', $request->conditions);
    })
    ->whereHas('locations', function ($query) use ($request){
        $locations = $request->locations;
        $query->where(function($builder) use($locations){
          $builder->where('town', 'like', '%' . $locations[0] . '%')
            ->orWhere('city', 'like', '%'.$locations[0].'%');
          unset($locations[0]); //remove first item as it is processed
          foreach($locations as $location) {
            $builder->orWhere('town', 'like', '%'.$location.'%')
              ->orWhere('city', 'like', '%'.$location.'%');
          }
        });
    });

如果您发现任何问题,请告诉我。 :)

答案 1 :(得分:0)

昨晚我设法搞清楚了。

我将with()移到了查询的顶部,并对位置进行了回调。

public static function newGetSearchResults($request)
    {
      return Service::with(['types', 'contacts', 'locations.datetimes', 'locations' => function($query) use($request) {

        $ran = false;
        foreach($request->locations as $location)
        {
          if(!$ran)
          {
            $query->Where('town', 'like', '%'.$location.'%')
            ->orWhere('city', 'like', '%'.$location.'%');
          }
          else
          {
            $query->orWhere('town', 'like', '%'.$location.'%')
            ->orWhere('city', 'like', '%'.$location.'%');
          }
          $ran = true;
        }
      }])
      ->whereHas('conditions', function ($query) use ($request){
        $query->whereIn('id', $request->conditions);
      })->get();
    }