Join 2 tables in a Single Eloquent Laravel using multiple where clause - php

here I'd like to find the solution to simplify my query to get data using eloquent in Laravel.
$room_id = Booking::whereBetween('from', [$request->from, $request->to])
->orWhereBetween('to', [$request->from, $request->to])
->where('from', '<=', $request->from, )
->where('to', '>=', $request->from)
->pluck('room_id');
$rooms = Room::whereNotIn('id', $room_id )->get();
So here I have 2 Eloquent operations to get Rooms which not included in the Booking Table with specified requirements. So far I have no problem with it, but can you guys give me best practice to simplify from what I do? Thank you.

Make sure that 'bookings' relation is written on your Room model.
$rooms = Room::whereDoesntHave('bookings', use($request) function($q){
$q->whereBetween('from', [$request->from, $request->to])
$q->orWhereBetween('to', [$request->from, $request->to])
$q->where('from', '<=', $request->from, )
$q->where('to', '>=', $request->from)
})->get();

Your can refer laravel relationship to add it in model and after that using whereHas to query join table:
https://laravel.com/docs/9.x/eloquent-relationships
Example:
With options
protected $with = [
'product_savour'
];
Relationship
public function product_savour()
{
return $this->hasMany(ProductSavour::class, 'product_id');
}
Query
$productQuery->whereHas('product_savour', function ($query) use ($filters) {
$query->whereHas('savour', function ($query) use ($filters) {
$query->whereHas('type', function ($query) use ($filters) {
$query->whereIn('id', $filters['savour']);
});
});
});

Related

Can not use where clause after using with clause in Laravel query

I am writing a query using with and then where clause in laravel.
$users = User::query()->with('roles')->where('name', '!=', 'customer')->get();
return $users;
But where clause is not working here. Customers are not excluded. I am providing the snap shot of the query result.
I think you need whereHas() :
use Illuminate\Database\Eloquent\Builder;
$users = User::query()
->with('roles')
->whereHas('roles', function (Builder $query) {
$query->where('name', '!=', 'customer');
})
->get();
return $users;
I suppose you trying to filter relation data in base query.
Try smth like that:
$users = User::query()->with([
'roles' => function ($q) {
$q->where('name', '!=', 'customer');
}])
->get();
return $users;
Doc

Laravel belongsToMany relation condition

I have created many-to-many relation using belongsToMany function:
class Doctor extends Model
{
...
public function categories()
{
return $this->belongsToMany('App\Category', 'doctors_to_categories', 'doctor_id', 'category_id');
}
...
}
Now I want to create query with many-to-many condition. In SQL in would be:
SELECT *
FROM `doctors`
JOIN `doctors_to_categories`
ON `doctors_to_categories`.`doctor_id` = `doctors`.`id`
WHERE `doctors_to_categories`.`category_id` = 1
I have tried to achieve this like:
$doctors = Doctor::with(['categories' => function($query) {
$query->where('category_id', '=', 1);
}])->get();
Or
$doctors = Doctor::with(['categories' => function($query) {
$query->where('categories.id', '=', 1);
}])->get();
But it is not working. Any ideas how it should be? Thanks for any help.
The with() function does not actually introduce a join in your query, it just loads the relation of all models as a second query. So the with() function couldn't possibly change the original result set.
What you are looking for is whereHas(). This will add a WHERE EXISTS clause to the existing query.
$doctors = Doctor::with('categories')->whereHas('categories', function ($query) {
$query->where('categories.id', 1);
})->get();
Using ->with() doesn't actually limit the results of the Doctor::...->get() query; it simply tells Laravel what to return in the relationships attribute. If you actually want to enforce returning only Doctors that have a category 1 relationship, you need to use whereHas():
$doctors = Doctor::whereHas('categories', function($query) {
$query->where('categories.id', '=', 1);
// `id` or `categories.id` should work, but `categories.id` is less ambigious
})->get();
You can add whereHas condition for this. Try code below:
$doctors = Doctor::with('categories')->whereHas('categories', function($query) {
$query->where('id', 1);
})->get();

How can I pick single record from one to many relation?

I have one to many relation based two tables users and games and there is also bridge table users_games (linking user_id to games).
I want to fetch a single record from games table based on provided game_id for specific user. I did some research and found whereHas() which is returning all games which are belongs to specific user. But I need to fetch one based on game_id. Can some one kindly let me know how can I fix issue in below script
$GameInfo = User::with('games')->whereHas('games', function ($query) use($request)
{
$query->where('game_id', '=', $request->game_id);
})->find(request()->user()->id);
Is this what you're trying to do?
$GameInfo = $request
->user()
->games()
->where('game_id', $request->game_id)
->first();
try this:
$GameInfo = User::with(['games' => function ($query) use($request)
{
$query->where('game_id', $request->game_id);
}])->whereHas('games', function ($query) use($request)
{
$query->where('game_id', '=', $request->game_id);
})->find(request()->user()->id);
If your relation 'games' is a hasMany() with table 'users_games', You can try this code
$GameInfo = User::with(['games' => function ($query) use($request)
{
$query->where('game_id', $request->game_id);
}])
->where('users.id', <user_id_variable>)
->first();
And the relation 'games' in User Model as
public function games()
{
return $this->hasMany('App\Models\UserGames', 'user_id', 'id');
}

OrderBY On model relationship eloquant on controller?

I am not able to find any perfect solution for it.
Controller:
$servicerequest = ServiceRequest::selectRaw('count(id) as totalservice,max(created_date) as last_service,service_provider_id,id,service_id,account_id,service_request,created_date')->with(['account' => function($first) use ($keyword) {
$first->select('id', 'restaurant_name')->orderBy('restaurant_name', 'DESC');
}])
->with(['serviceProvider' => function($query) use ($keyword) {
$query->select('id', 'company_name');
}])->groupBy('account_id')
->orderBy('company_name', 'DESC')
->paginate(100);
I need an order by on model relation table field and that effect on main table data. because it's and one to one relationship so no need to order by on the inside.
Like I need to the orderby whole on relations data.
Collection:
You must make join your relation table to used orderBy relation table.
You can try this code.
$servicerequest = ServiceRequest::selectRaw('count(id) as totalservice, max(created_date) as last_service,service_provider_id,id,service_id,account_id,service_request,created_date, SERVICEPROVIDERTABLE.company_name')
->join('serviceProvider', 'SERVICEPROVIDERTABLE.id', '=', 'SERVICEREQUESTTABLE.service_provider_id')
->with([
'account' => function ($first) use ($keyword) {
$first->select('id', 'restaurant_name')
->orderBy('restaurant_name', 'DESC');
}
])
//->with([
// 'serviceProvider' => function ($query) use ($keyword) {
// $query->select('id', 'company_name');
// }
//])
->groupBy('account_id')
->orderBy('SERVICEPROVIDERTABLE.company_name', 'DESC')
->paginate(100);
i hope this works.

Laravel OrderBy Relationship count with pagination

I have many projects and each has many orders, some completed, some not.
I want to order them by the amount of completed orders like this:
$products = $products->orderBy(function($product) {
return $product->orders->where('status', 2)->count();
})->paginate(15);
I know the order call doesn't work like this but this is the best was show the problem. SortBy doesn't work because I want to use pagination.
Finally found a good solution for the problem:
$products = $products->join('orders', function ($join) {
$join->on('orders.product_id', '=', 'products.id')
->where('orders.status', '=', 2);
})
->groupBy('products.id')
->orderBy('count', $order)
->select((['products.*', DB::raw('COUNT(orders.product_id) as count')]))->paginate(50);
Try this if it works:
$categories = Prodcuts::with(array('orders' => function($query) {
$query->select(DB::raw('SELECT * count(status) WHERE status = 2 as count'))
$query->orderBy('MAX(count)')
}))->paginate(15);
return View::make('products.index', compact('categories'));
Note: This is not tested.
From 5.2 on wards you can use the withCount for counting relationship result.
In this case the
$products = $products->withCount(['orders' => function ($query) {
$query->where('status', 2);
}]);
Reference : https://laravel.com/docs/5.2/eloquent-relationships

Categories