OrderBY On model relationship eloquant on controller? - php

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.

Related

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

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']);
});
});
});

filtering the model based on a relationship laravel

So my code is
$categories=Category::where('user_id', $store->id)->whereHas('childrenCategories', function($q) use ($id){
$q->where('user_id', $id);
})->orwhereHas('products', function($q) use ($id) {
$q->where('auth_id', $id);
})->with('products', 'childrenCategories')->latest()->get();
I want to get all children categories with and products with given id but this code doesn't seem to work. As children categories with user_id other than id are also being returned. Sorry, I am relatively new to Laravel. And I thought this would be a good platform to ask. Also, I can share the relationships if you want me to.
I solved this with the following. Thanks, #lagbox for your time.
$categories = Category::with(['childrenCategories' =>
$childrenClosure = function ($query) use ($id) {$query->where('user_id', $id);}, 'products'
=> $productsClosure = function ($query) use ($id) {$query->where('auth_id', $id);}])
->where('user_id', $store->id)
->where(function ($query) use ($childrenClosure, $productsClosure) {$query->whereHas('childrenCategories', $childrenClosure)
->orWhereHas('products', $productsClosure);})
->latest()
->get();

Laravel - Nested relationship, order parent model by most recent nested

Having a hard time understanding how to order my Laravel model by a nested relationship.
Here are the Models.
User.php
// Has many small_groups through a pivot table
public function small_groups()
{
return $this->belongsToMany('App\Models\SmallGroup')->withPivot('type')->withTimestamps();
}
SmallGroup.php
// Has many SmallGroupLessons
public function small_group_lessons()
{
return $this->hasMany('App\Models\SmallGroupLesson');
}
SmallGroupLessons.php
// Has many SmallGroupLessonComments
public function small_group_lesson_comments()
{
return $this->hasMany('App\Models\SmallGroupLessonComment');
}
SmallGroupLessonsComment.php
// Belongs to SmallGroupLesson
public function small_group_lesson()
{
return $this->belongsTo('App\Models\SmallGroupLesson');
}
What's I'm trying to do, is pull all of the user's small groups, ordered by the most recent SmallGroupLessonComment if one exists. I've been doing some research, and it sounds like using Laravels ORM in this use case will not work. However, I'm not entirely sure on how to create the join on the nested relationship.
I tried the following, but this only pulls in the most latest SmallGroupLessonComment, however, it does not order the entire result set.
$small_groups = $user->small_groups()->with([
'small_group_lessons' => function($q) {
$q->with([
'latest_comment' => function($q) {
$q->orderBy('created_at', 'asc');
}
]);
}
])->paginate($limit);
Update
Was able to solve it via the following...
$small_groups = $user->small_groups()->with([
'small_group_lessons' => function($q) {
$q->with([
'latest_comment' => function($q) {
$q->orderBy('created_at', 'asc');
}
]);
}
])
->leftJoin('small_group_lessons', 'small_group_lessons.small_group_id', '=', 'small_groups.id')
->leftJoin('small_group_lesson_comments', 'small_group_lesson_comments.small_group_lesson_id', '=', 'small_group_lessons.id')
->orderBy('small_group_lesson_comments.created_at', 'desc')
->paginate($limit);
Update #2
The above doesn't work. I get multiple small groups back that are the same item.
Update #3
This query is pretty close, but it's just ordered by the most recent SmallGroupLesson. Ideally, we order by the SmallGroupLessonComment 🤔
$small_groups = $user->small_groups()->with(
[
'small_group_lessons' => function($q) {
$q->with('latest_comment');
$q->orderBy('created_at', 'desc');
}
],
)
->orderBy(
SmallGroupLesson::select('created_at')
->whereColumn('small_group_id', 'small_groups.id')
->orderBy(SmallGroupLessonComment::select('created_at')
->whereColumn('small_group_lesson_id', 'small_group_lessons.id')
->orderBy('created_at', 'desc')
->limit(1), 'desc')
->limit(1), 'desc'
)
->paginate();
$data=User::select('*')->leftJoin('small_group_lessons','small_group_lessons.user_id','user.id')
->ordeBy('small_group_lessons.created_at','DESC')->get();
try like this
I was able to solve it via the following. Ordering based off the latest comment now works correctly.
$small_groups = $user->small_groups()->with([
'small_group_lessons' => function($q) {
$q->with('latest_comment');
$q->orderBy('created_at', 'desc');
}],
)
->orderBy(
SmallGroupLesson::select('small_group_lesson_comments.created_at')
->join('small_group_lesson_comments', 'small_group_lessons.id', '=', 'small_group_lesson_comments.small_group_lesson_id')
->whereColumn('small_group_id', 'small_groups.id')
->latest()
->limit(1), 'desc'
)
->paginate();

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');
}

Categories