I have a Eloquent query and I am using query scope. I have a km column in my table and I am passing kmFrom and KmTo values as post data. Now I am doing a eloquent whereBetween and its returning wrong results when I search for km.
For example if I pass kmFrom = 1000 and kmTo = 2000. Its giving me results which are not in between these two values.
Eloquent:
Product::categoriesCategoryId($categoryId)
->km($kmFrom, $kmTo)->get();
Query Scope for the km:
public function scopeKm($query, $kmFrom, $kmTo)
{
if(($kmFrom) && ($kmTo)){
return $query->whereBetween('km', ["$kmFrom", "$kmTo"]);
}
return $query;
}
Please assist what wrong I am doing.
It's different approach to doing same thing
public function scopeKm($query, $kmFrom, $kmTo)
{
if(($kmFrom) && ($kmTo)){
return $query->where('km','>' ,$kmFrom])->where('km','<',$kmTo);
}
return $query;
}
this will work same
hope this will help you!
Related
User Model :
public function favorites()
{
return $this->hasMany(Favorite::class);
}
Controller :
//return auth()->user()->favorites()->get();
//return auth()->user()->favorites;
can someone explain the difference betwen the two codes ?
and when i should use each one?
Let me explain it practically:
If the above query looks like this
// return auth()->user()->favorites()->where('active', true)->get();
// return auth()->user()->favorites->where('active', true);
then its SQL query be like this
// SQL of first query
select * from `favorites` where `favorites`.`user_id` = 1 and `favorites`.`user_id` is not null and `active` = 1
// SQL of second query
select * from `favorites` where `favorites`.`user_id` = 1 and `favorites`.`user_id` is not null
Did you see differences in two SQL?
Now, Let me explain it in words:
If you add some condition after favorites() like above, it will fetch all filtered result from database. But if you add some condition after favorites it will filter the result which is already fetched from the database.
Although, I'm not good at explanations, I hope you understand clearly between the two codes.
I have a selection of plots which each belong to a development by a hasManyThrough relationship through housetypes. I want to filter these by development on their overview page. Plots has a housetype_id column and housetypes has a development_id column.
public function plots()
{
return $this->hasManyThrough(Plot::class, Housetype::class);
}
When I use my filter it returns the developments ID number as $development, I then need this to only show plots which are linked to that development.
I have looked into using whereHas or Join methods but have been unable to figure this out. Current filter scope is below. Thanks
public function scopeFilterDevelopment($query)
{
$development = request()->input('filter_development');
if ($development == "") {
return;
}
if(!empty($development)){
$query->where('development_id', $development);
}
}
If I can understand it right you wish to assert a condition on other Model, HasMany will load all the objects to the related model once the query is completed. Eloquent then binds the related model objects to each.
Try joins from Laravel instead. I feel this is what you exactly want: https://laravel.com/docs/5.8/queries#joins
I would use whereHas to filter the relationship:
YourModel::whereHas('plots', function($query) {
$query->filterDevelopment();
})->get();
I would also edit the query scope not to rely on the request global function, but instead pass the development of value as a parameter.
you have make a leftjon and then use when, you dont have to use
if(!empty($development)){
$query->where('development_id', $development);
}
this any more, you can use
->when($development=="" ? false : true, function($query) use ($development){
return $query->where('development_id', $development);
})
this is a full example
$queryBuilder = DB::table('facturas')->
leftJoin('clientes','clientes.id','=','facturas.clientes_id')->
select('facturas.estados_id as estado','facturas.numero as
numero',DB::raw('concat(clientes.nombre," ",clientes.apellido) as cliente'))->
when($estados===null ? false: true,function($query) use ($estados){
return $query->whereIn('facturas.estados_id', $estados);
})
It was a whereHas that solved this in the end! (another developer at work walked me through this)
Relationship -
public function housetype()
{
return $this->belongsTo(Housetype::class);
}
Function -
public function scopeFilterDevelopment($query)
{
if (request()->input('filter_development') == "") {
return;
}else{
$query->whereHas('housetype', function($housetype){
$housetype->where('development_id', request()->input('filter_development'));
});
}
}
This then returns any plot where its housetype has a matching development_id for the filter_development from the request.
Thanks for everyone's input
I have a mutattor in an eloquent model that generates a "status" atribute.
public function getStatusAttribute(){
if(){
return "enabled";
}
else
{
return "disabled";
}
}
Can I use?
$query = Anuncio::query();
$query->where('status', "enabled" );
return $query->get();
I seems that I cannot. I getting "status" column not defined. How can I get around this problem?
No doesn't works it works on model level
you can use after query from database in collection result
No, when you are doing a query you are asking the database, therefor there needs to be a column status.
There is a way, retrieve x elements from the database and use the Laravel Collection method where(). This is not optimal if you have many elements in teh database, it will retrieve all of them.
Anuncio::all()->where('status', 'enabled')->all();
I have a one-to-many relationship, which works perfectly when using the relationship as a property on a query, but when i try to use it as a method it always return empty.
User Model
public function reports()
{
return $this->hasMany('App\Report', Report::COL_USER_ID, self::COL_ID);
}
Report Model
public function user()
{
return $this->hasOne('App\User', User::COL_ID, self::COL_USER_ID);
}
This Works
$reports = User::find($id)->reports;
This Doesn't and i need something like this
$reports = User::find($id)->reports()->orderBy(Report::COL_CREATED_AT, self::ORDER_BY_DESC);
According to the eloquent doc, "since all relationships also serve as query builders, you can add further constraints", so that should totally be retrieving the proper data, am I missing something? Thanks in advance for any help
You need to use get method to get actual results, so you should use:
$reports = User::find($id)->reports()->orderBy(Report::COL_CREATED_AT, self::ORDER_BY_DESC)->get();
instead of only:
$reports = User::find($id)->reports()->orderBy(Report::COL_CREATED_AT, self::ORDER_BY_DESC);
In your case, you only created query and haven't get any results from database. That's why you don't get any results.
And the reason why:
$reports = User::find($id)->reports;
works is because it's shortcut for:
$reports = User::find($id)->reports()->get();
If you try to use:
$reports = User::find($id)->reports();
only you won't get any results either.
I have a problem with Laravel 5.1: Eloquent relationship hasmany, Limit records I have 2 tables: feeds, comments. The request is to obtain 5 feeds and comments accordingly to each particular feed. I am currently using the below query:
public function getFeed($user_id){
return Feed::whereUserId($user_id)->with(['comments'])->take(10)->get()->map(function ($feed) {
$feed->comments = $feed->comments->take(5);
return $feed;
});
}
However, it returns all the comments.
My thinking was that the $feed->comments = $feed->comments->take(5); line doesn't work. I only want to get 5 comments for each feed, do you have any advise? Any comments are highly appreciated. Thank you!
It's better late than never, I was facing the same issue yesterday and ended up by sets the entire relations array on the model.
So in your case it will be like this:
return Feed::whereUserId($user_id)->take(10)->get()->map(function($feed) {
$feed->setRelation('comments', $feed->comments->take(5));
return $feed;
});
I was facing the same issue for over a month now. I just wanted to optimize the query because it was taking almost 1.5 sec to load desired data from 1 million records.
I leveraged Eloquent ORM Collection Load() method. This reduces the load time to just 300 ms.
In your case,
return Feed::whereUserId($user_id)
->get()
->each(function ($feed) {
$feed->load('comments')->take(5);
})
});
If it's something that will apply in all cases, you can adjust the relationship in the Feed model like this:
public function comments() {
return $this->hasMany('App\Comment')->limit(5);
}
$feed= Feed::whereUserId($userId)->with(['comments'])->get()->map(function ($query) {
$query->setRelation('comments', $query->comments->take(10));
return $query;
});
Feed::whereUserId($user_id)->with([
'comments' => function($query) {
// You should limit the comments by editing the
// relationships query not the main query.
$query->take(5);
}
])->take(10)->get();
This way you can limit the feed count you want and the comment count each feed has.
the take() eloquent method just adds 'limit' word at the end of the query. this type of query is more complex and isn't supported by vanilla eloquent.
fortunately, there is an additional package called eloquent-eager-limit, which helps with this problem. in order to make it work, install that package by using composer require staudenmeir/eloquent-eager-limit command and put use \Staudenmeir\EloquentEagerLimit\HasEagerLimit; line inside both parent and children model classes.
The error might be here
$feed->comments = $feed->comments->take(5);
Which should be
$feed->comments = $feed->comments->take(5)->get();
I will suggest you write in this way
$feed->load(['comments' => function($query){ return $query->take(5); }])