laravel query join with only latest record - php

I'm using Laravel 5.3 and trying to return a heist with it's product and only the latest order and with the latest price history. Both joins don't return anything but if I remove the $q->latest()->first(); and replace it with a simple orderBy() I get all results. My query is:
$data = $heist->with(['product'=> function($query) {
$query->with(['orders' => function($q) {
return $q->latest()->first();
}]);
$query->with(['price_history' => function($q) {
return $q->latest()->first();
}]);
}])->orderBy('completed_at', 'DESC')->orderBy('active', 'DESC')->get();

As discussed in the comments, I believe the simplest way of doing this is
$heists = $heist->with(['product'=> function($query) {
$query->with([
'orders' => function($q) {
return $q->orderBy('created_at', 'desc')->take(1)->get();
},
'price_history' => function($q) {
return $q->orderBy('created_at', 'desc')->take(1)->get();
}
]);
}])->orderBy('completed_at', 'desc')->orderBy('active', 'desc')->get();
Hope this helps :)

Calling first() is the same as calling take(1)->get()[0];
Which means limit the amount returned to 1 and return it. What you want is just the limit part. So if you change first() to take(1).
Update
$data = $heist->with([
'product'=> function($query) {
$query->with(
[
'orders' => function($q) {
$q->latest()->take(1);
},
'price_history' => function($q) {
$q->latest()->take(1);
}
]
);
}
])->orderBy('completed_at', 'DESC')->orderBy('active', 'DESC')->get();

Related

Laravel Eloquent: How to add where condition from the with function model relation

Anyone can help me? How to add where condition from the with function model relation.
I tried ->where('driver.group_id',$group_id) but it does not work. please look my code below.
public function getDriversDailyEarnings()
{
$group_id = Auth::user()->group->id;
$today = Carbon::today();
$data = DailyEarnings::with(['payout_cost',
'status:id,name',
'driver' => function ($query) {
$query->with('user');
}])
->where('driver.group_id',$group_id)
->whereDate('created_at', $today)
->get();
return response()->json($data, 200);
}
You can try this. Haven't tested it yet.
DailyEarnings::with([
'payout_cost',
'status:id,name'
'driver' => function($query) {
$query->where('group_id', auth()->user()->group->id)->with('user');
}
])
->whereHas('driver', function($query) {
$query->where('group_id', auth()->user()->group->id);
})
->whereDate('created_at', now()->format('Y-m-d'))
->get();
To pass other clauses to a relation, just use it inside an array, where the key and the name of the relation and the value is a function that receives an instance of the query, something like this:
public function getDriversDailyEarnings()
{
$data = DailyEarnings::with([
'payout_cost' => function ($myWithQuery) {
$myWithQuery->where('column-of-relation-here', 'value-here')
->orWhere('name', 'LIKE', '%Steve%');;
}
])->get();
return response()->json($data, 200);
}
Perhaps something like this:
// ->where('driver.group_id',$group_id)
->whereHas('driver', fn($qry) => $qry->where('group_id', $group_id)) // if group_id a field on driver

Filtering in Laravel using regex

I'm trying to filter products based on query string. My goal is to get products from a collection if it's given, otherwise get every product. Could someone help me what's wrong with the following code?
$products = \App\Product::where([
'collection' => (request()->has('collection')) ? request('collection') : '[a-z]+',
'type' => (request()->has('type')) ? request('type') : '[a-z]+'
])->get();
PS.: I've also tried with 'regex:/[a-z]+', it's not working...
$products = \App\Product::where(['collection' => (request()->has('collection')) ? request('collection') : 'regex:/[a-z]+'])->get();
What you can do is use when eloquent clause, so your where clause for collections will be triggered only when the request('collection') exists, same logis applie to type as well.
$products = \App\Product::
when(request()->has('collection'), function ($q) {
return $q->where('collection', request('collection'));
});
->when(request()->has('type'), function ($q) {
return $q->where('type', request('type'));
})
->get();
Or another way if you have your request values assigned to a variable something like:
$collection = request('collection');
$type= request('type');
$products = \App\Product::
when(!empty($collection), function ($q) use ($collection) {
return $q->where('collection', $collection);
});
->when(!empty($type), function ($q) use ($type) {
return $q->where('type', $type);
})
->get();

conditional query running in relationship in Laravel

here I have a code that I query inside a relationship that I want just 1 part to be executed if the user send the variable to me if not that query didn't run at all here is my code I commented in my code where I want my condition:
$bed_count = $request->get('bed_count');
$data = Accommodation::with(['city','accommodationRoomsLimited.roomPricingHistorySearch' =>function($query) use($from_date,$to_date){
$query->whereDate('from_date', '<=', $from_date);
$query->whereDate('to_date', '>=', $to_date);
},'accommodationRoomsLimited' => function($q) use($bed_count){
//here is I want my query to be executed if the user sends bed_count if not the code should skip this part
$q->orWhere('bed_count',$bed_count);
}])
Not clear what are you trying to achieve.
If you want to eager load accommodationRoomsLimited all the time,
But when user has provided bed count, you need to filter those accommodationRoomsLimited with this bed count.
If that's so
$bed_count = $request->get('bed_count');
$data = Accommodation::with([
'city',
'accommodationRoomsLimited.roomPricingHistorySearch' => function($query) use($from_date,$to_date) {
$query->whereDate('from_date', '<=', $from_date);
$query->whereDate('to_date', '>=', $to_date);
},
'accommodationRoomsLimited' => function($q) use($bed_count) {
if ($bed_count) {
$q->where('bed_count',$bed_count);
}
}
]);
If you only want to eager load accommodationRoomsLimited only when user has provided bed count.
Then
$bed_count = $request->get('bed_count');
$data = Accommodation::with([
'city',
'accommodationRoomsLimited.roomPricingHistorySearch' => function($query) use($from_date,$to_date) {
$query->whereDate('from_date', '<=', $from_date);
$query->whereDate('to_date', '>=', $to_date);
},
])
->when($bed_count, function ($query, $bed_count) {
$query->with([
'accommodationRoomsLimited' => function($q) use($bed_count) {
$q->where('bed_count',$bed_count);
}
]);
});

issue in laravel relationship with multiple model

user has relation with creater one to one but creater has relation with archive belongsToMany
$creatorQuery = User::query();
$cultivator_id = 2;
$creatorQuery = $creatorQuery->select('id', 'name', 'email', 'role');
$creatorQuery = $creatorQuery->with('creater', function($q) {
$q->whereHas('archive', function($q) use($cultivator_id) {
$query->where('caltivater_id', $cultivator_id);
});
});
$creators = $creatorQuery->get();
showing error mb_strpos() expects parameter 1 to be string, object given
function is supposed to be passed into creater, so you need to change your call to be a key/value array:
$creatorQuery = $creatorQuery->with(['creater' => function($q) use($cultivator_id) {
$q->whereHas('archive', function($q) use($cultivator_id) {
$query->where('caltivater_id', $cultivator_id);
});
}]);
You've said you want to get users by their caltivater_id value defined in Archive model. Use nested whereHas():
$creators = User::whereHas('creator', function($q) use($cultivator_id) {
$q->whereHas('archive', function($q) use($cultivator_id) {
$q->where('caltivater_id', $cultivator_id);
});
})
->with('creators')
->get();
Or use dot notation:
$creators = User::whereHas('creator.archive', function($q) use($cultivator_id) {
$q->where('caltivater_id', $cultivator_id);
})
->with('creators')
->get();

Laravel two wherehas queries not working

I would like to assign a group to users which have a role student and have also a particular selected group. There is a users table, which has pivot tables: role_user and group_user with roles and groups tables. Below is the code for the controller where I am trying to execute the query:
$this->validate($request, [
'add-group' => 'required',
'where-group' => 'required'
]);
$selectedGroup = $request->input('add-group');
$whereGroupId = $request->input('where-group');
$users = User::whereHas('roles', function($q) {
$q->where('name', 'student');
})->whereHas('groups', function($q) {
$q->where('id', $whereGroupId);
})->get();
$selectedGroup = Group::whereId($selectedGroup)->first();
$users->assignGroup($selectedGroup);
You need to use the orWhereHas clause for the second half of the query.
Secondly, your $whereGroupId variable is not in the inner-function's scope, add a use($whereGroupId) statement to include it in the function's scope.
$users = User::whereHas('roles', function($q) {
$q->where('name', 'student');
})->orWhereHas('groups', function($q) use ($whereGroupId) { // <-- Change this
$q->where('id', $whereGroupId);
})->get();
You had syntax error and a missing use to pass whereGroupId. I have no clue what assignGroup does, but this should fix the code you have.
$this->validate($request, [
'add-group' => 'required',
'where-group' => 'required'
]);
$selectedGroup = $request->input('add-group');
$whereGroupId = $request->input('where-group');
$users = User::whereHas('roles', function ($q) {
$q->where('name', 'student');
})
->whereHas('groups', function ($q) use ($whereGroupId) {
$q->where('id', $whereGroupId);
})->get();
$selectedGroup = Group::whereId($selectedGroup)->first();
$users->assignGroup($selectedGroup);

Categories