Reputation: 237
I creating API to filter restaurants. When user find restaurant by district, I want show restaurants at this district and restaurants ship food to this district. So, I used orWhereHas.
function searchRestaurant(Request $request) {
$city = $request->input('city');
$district = $request->input('district');
$category = $request->input('category');
$fee = $request->input('fee');
$restaurants = new Restaurant();
if($district) {
$restaurants = $restaurants->where('district_id', $district)
->orWhereHas('shipdistricts', function($q) use ($district) {
$q->where('id', $district);
});
}
elseif($city && !$district) {
$restaurants = $restaurants->where('city_id', $city);
}
if($category){
$restaurants = $restaurants->whereHas('categories', function($q) use ($category) {
$q->where('id', $category);
});
}
return response()->json([
'success' => true,
'data' => $restaurants->get()->unique()->toArray()
]);
}
Restaurant Model
public function shipdistricts()
{
return $this->belongsToMany(District::class, 'restaurant_districts', 'restaurant_id');
}
public function categories()
{
return $this->belongsToMany(Category::class,'restaurant_categories_relation','restaurant_id');
}
But when I request category, the result not correctly. Why? Sorry my English is not good!
Upvotes: 1
Views: 2702
Reputation: 6544
The problem is most likely that you are not encapsulating your orWhere()
properly. This will yield a query that isn't very obvious and only functions due to the precedence of AND
over OR
.
So you basically have to wrap the district
/city
conditionals in a where(function ($query) { })
block. Together with the nice usage of when($condition, $callback)
, this yields a result like this:
function searchRestaurant(Request $request)
{
$city = $request->input('city');
$district = $request->input('district');
$category = $request->input('category');
$fee = $request->input('fee');
$restaurants = Restaurant::query()
->when($district, function ($query, $bool) use ($district) {
$query->where(function (query) use ($district) {
$query->where('district_id', $district)
->orWhereHas('shipdistricts', function ($query) use ($district) {
$query->where('id', $district);
});
});
})
->when($city && !$district, function ($query, $bool) use ($city) {
$query->where('city_id', $city);
})
->when($category, function ($query, $bool) use ($category) {
$query->whereHas('categories', function ($query) use ($category) {
$query->where('id', $category);
});
})
->get();
return response()->json([
'success' => true,
'data' => $restaurants->toArray(),
]);
}
You are not required to use unique()
on the result either as there can only be one instance per Restaurant
anyway.
Upvotes: 3
Reputation: 371
I believe that your issue is that you created a new $restaurants = new Restaurant();
and you are trying to query. Please use this query
:
$query = Restaurant::query();
Upvotes: 0