I have two tables Songs (belongsTo App\Host) and Hosts (hasMany App\Song). My Songs table has an attempts column and my Host table has a skip_threshold. I would like to query out all Songs that have not met its related Host's skip threshold.
How can I do this?
I have tried something like this:
return $songs = Song::whereIn('host_id', $available_hosts)
->where('attempts', '<', $songs->host->skip_threshold)->get();
I've attempted to make use of Eloquent relationship querying, but from testing I see this won't work. I would like to try and use Eloquent to do this so I can take advantage of eager loading related data in my blade templates.
You could try
$songs = Song::whereHas('host', function($query) {
$query->where('skip_threshold', '>', DB::raw('songs.attempts'));
})->get();
If I'm understanding what you're looking for, you can chain together where clauses, like so:
$songs = Song::whereHas('host', function($query) {
$query->where('skip_threshold', '>', DB::raw('songs.attempts'));
})->whereIn('host_id', $available_hosts)->get();
Related
hello I am new to laravel and maybe I am a bit confused between eloquent and query builder way for writing a query but anyway can you please tell me what could be the best eloquent way to retrieve info like this in laravel 6 or 7
User > hasMany > Recipes
Recipe > belongsTo > User
I want to check if user id 2 present in users table then get only one post which id is 3
Query builder is for explicitly building SQL queries, and does not return instances of your models. Eloquent query builder, is similar but the result will contain the model(s) loaded with all their attributes, and has some handy functions for querying the relations you define in your models.
Given the limited information in your post, I am assuming when you say a post, you mean a recipe:
Query Builder:
DB::table('users')
->join('recipes', 'recipes.user_id', '=', 'users.id')
->select(['users.some_col', ... 'recipes.some_col'])
->where('users.id', 2)
->get();
If you have your models setup with the relations. You can use Eloquent like so:
User::where('id', 2)->with('recipes')->get();
If I understand you correctly it would be like this:
User::whereId($userId) //asuming it is 2
->with(['recipes' => function($q) use($recipeId) {
$q->where('id', $recipeId); //assuming it is 3
}])->first();
you can do this if i understand correctly:
$user = User::findOrFail(2); //auto 404 if user not found
$recipe = $user->Recipes()->where('id',3)->first();
You may use conditional eager loading for better performance.
$userId = 2;
$receiptId = 3;
$user = User::with(['receipts'=> function ($query) use($receiptId){
$query->where('id', $receiptId);
}
])->find($userId)
This is my model
User
Role
and relationship between of those models are many to many.
I want to create query like this:
return User::with('roles')->orderBy('roles.id')->paginate();
I don't want join because I created a base class for every model. I also don't want use orderBy after get because it must load all of my data and after that I should be able to sort and paginate it. So it is not a very good idea.
You can try something like this:
return User::with(['roles' => function ($query) {
$query->orderBy('id', 'desc');
}])->paginate();
But this will only order the eager loading attributes, but if you are interested to use join you can have something like this:
return User::with('roles')
->join('roles', 'user.id', '=', 'roles.user_id')
->orderBy('roles.id', 'desc')
->paginate();
In this you can easily use paginate which is your main concern.
Hope this helps.
User::where('role_id','!=','0')->orderBy('role_id','DESC')->paginate(10);
In my application I have updated a relationship from one-to-many to many-to-many and I'm trying to figure out a way to persist associated functionality.
Let's say I have two related tables, e.g. dogs and owners. If I have an array of owners and I'm trying to get a list of dogs id's for those owners, how should I do it eloquently?
Similar question was asked here:
https://laracasts.com/discuss/channels/laravel/getting-many-to-many-related-data-for-an-array-of-elements
So, How would I get the Dog models where Owner is in an array ?
Same thing as $associatedDogs = Dog::whereIn('owner_id',$ListOfOwners)->get(); is for a One-To-Many relationship, but for Many-to-Many.
Use the whereHas() method:
$dogs = Dog::whereHas('owners', function($q) use($ownerIds) {
$q->whereIn('id', $ownerIds);
})->get();
I tried the two suggested solutions but I was getting an error that said that id was not unique.
I solved like this:
$dogs = Dog::whereHas('owners', function($q) use($ownerIds) {
$q->whereIn('owner_id', $ownerIds);
})->get();
Try
$associateDogs = Dog::with(['owners' => function($query) use ($listOfOwners) {
$query->whereIn('id', $listOfOwners);
}])->get();
I'm trying to get "reviews" from my database where the user is from MX (for example) so, I have this:
Review::with(array('user' => function($query)
{
$query->where('country_code', '=', 'MX');
}))
->with('user.country','pictures')
->where('shop_id',Input::get('id'))
->orderBy('id','DESC'))
->get()
->toArray()
But seems to be like where('country_code', '=', 'MX') is not taken into account because retrieve all reviews and I just want the reviews written by the user from MX.
user and picture inside with are functions within my User model
country_code is a field from users table
The goal is: Just get the reviews written by a user from the country specified, and was testing something like this:
Review::where('shop_id',Input::get('id'))
->with('user.country','pictures')
->where('users.country_code','MX')
->orderBy('id','DESC'))
->get()
->toArray()
But is not working as well because says: Unknow column users.country_code in where....
You want to do a query that filters based on the relation. Eager loading constraints only constrain the records that come with your main result set.
Review::whereHas('users', function ($q)
{
$q->where('country_code', 'MX');
})
->with('user','pictures')
->where('shop_id',Input::get('id'))
->orderBy('id','DESC'))
->get();
The whereHas is saying ... give me only Reviews that have a User with country_code=MX.
Reference
Laravel Docs - Eloquent - Querying Relations
If you want reviews written by a certain user or group of users you don't want to use eager loading. Try this:
Review::with(array('user', 'pictures'))
->join('users', 'reviews.user_id', '=', 'users.id)
->where('users.country_code', '=', 'MX')
->where('reviews.shop_id', Input::get('id'))
->orderBy('reviews.id', 'DESC'))
->get();
Using Laravel 4 I have the following models and relations: Event which hasMany Record which hasMany Item. What I would like to do is something like this
Item::where('events.event_type_id', 2)->paginate(50);
This of cause doesn't work as Eloquent doesn't JOIN the models together when retrieving the records. So how do I go about this without just writing the SQL myself (which I would like to avoid as I want to use pagination).
What you want is eager loading.
It works like this if you want to specify additional constraints:
Item::with(array('events' => function($query) {
return $query->where('event_type_id', 2);
}))->paginate(50);
There is a pull request pending here https://github.com/laravel/framework/pull/1951.
This will allow you to use a constraint on the has() method, something like this:
$results = Foo::has(array('bars' => function($query)
{
$query->where('title', 'LIKE', '%baz%');
}))
->with('bars')
->get();
The idea being you only return Foos that have related Bars that contain the string 'baz' in its title column.
It's also discussed here: https://github.com/laravel/framework/issues/1166. Hopefully it will be merged in soon. Works fine for me when I update my local copy of the Builder class with the updated code in the pull request.