querying many-to-many-relationship laravel - php

I have a many-to-many relationship with models Competition and Season with a pivot table named competition_season.
Season->belongsToMany->Competitions->hasMany->Teams->hasMany->Players
I want to query the data of all players in a team in a specific season.
something like
\App\Player::with('team.competition.season')->where('team.competition.season.id', 2);
However since season is a collection (competition has many seasons) at this moment i can never query it like this.
Can someone point me in the right direction to properly select all players in a team in a particular season?

First, you need to add relation hasManyTrough at your model (read more about at: has-many-through)
Then, all you need is "whereHas"
$players = \App\Player::with('season')->whereHas('season', function($q){
$q->where('season.id', '=', 2);
})->get();

Related

Laravel find rows by nested relationship column

I have 2 tables reserves and chats, chats belongTo reserves and I want to get all chats where chat.reserve.user_id = Auth::id(). How can I do that in laravel.
I don`t know your models name (need more code in question), but try use
$chats = Chat::query()->whereHas('reserves', function ($q) use ($authID){
$q->where('user_id', $authID);
})->get();
where 'reserves' your relationship and have field user_id. Maybe needed full path to field like 'reserves'.'user_id'
Also look at documentation

Adding where() on with() eager loading.

I have a little but intricate problem here, I'll try to explain it as best I can.
First I have 3 models, Course, Student, and Quiz,
Student and Course are in a Many to Many relationship
Student and Quiz are in a Many to Many relationship
Quiz and Course are in a One to Many relationship respectively
And I have this following query:
$course = Course::whereSlug($slug)->first(); // Some Course
$quizzes = $course->students()->with('quizzes'); // <-- Here lies the problem.
In the last sentence I want to edit this query to be something like this:
$quizzes = $course->students()->with('quizzes)->where('course_id', $course->id);
I want to do it like that because I want to only grab the quizzes that are related to both the Student model and the Course model.
To give you the full picture, after that I loop through the $students variable in a vue component like this:
<div v-for="student in students"></div>
I am looping with the Student model Because I'm also retrieving different properties other than the quizzes.
But of course when I do it like the query up there I end up retrieving all quizzess for the all students that has a course_id = $course_id.
Required
I want to filter the results to get the quizzes of a student ONLY if they have a course_id of whatever the current courses's id is.
You can use whereHas function to do your job, something like this:
$quizzes = $course
->students()
->whereHas('quizzes', function($q){
$q->where('course_id', $course->id);
})
->with('quizzes)
->get();
I think if you follow the convention you should take Quiz model with students and course cross checked, its upto you. You can find out more on Laravel Documentation Hope this resolves your problem.
Of course after I posted the question I found the answer online randomly, here it is:
$quizzes = $course->students()->with(['quizzes'=> function($query) use ($course) {
$query->where('course_id', $course->id);
}])->get();

Tables with two or more foreign keys in Laravel

I have three database tables in my application. As an example, here is what I have now:
items TABLE: id, quantity, price, month_id (FK), department_id (FK)
months TABLE: id, month
department TABLE: id, department
I have already defined hasMany and belongsTo relations on the models. With these relations, I'm able to perform the query App\Month::first()->items to retrieve all first month items. However, if I want to query on both month and department, what is the best way to do it in this case?
I can certainly do it like this:
$month = App\Month::first();
$month->items()->where('department_id', '3')->get();
Is there more elegant way of doing this query?
First of all you can tell Eloquent to eagerly load needed relations to get better performance. You can do this by using with() method and defiling all needed relations - see http://laravel.com/docs/5.0/eloquent#eager-loading for more details.
Moreover, if you want to apply some additional criteria on loaded relations, you can do so using the same with method, but using different syntax to define relations and criteria:
$users = User::with(['posts' => function($query)
{
$query->where('title', 'like', '%first%');
}])->get();

remove from select laravel

I'm creating a system where a club has multiple teams, and in every team can be users (users can be in multiple teams)
Now all the eloquent things work for selecting all the things :)
but now I want to generate a list of all users from the a club that are NOT in the team already
now I just normal select the users by doing the following:
$team->club->users()->lists('name','id')
This is on the team page, so first I get the club the team is from and then I get all the users, and only select the name and Id.
I've used Laravel pretty extensively over the last six months and I think what you're looking for is the "whereNotIn" functionality of Eloquent.
Here's an example, based on my application:
$user = User::whereNotIn('id', function($query) {
$query->select('id')
->from('hospital_user')
->where('hospital_user.hospital_id', '=', 54);
})->lists('email', 'id');
This could be simplified like:
$hospital = Hospital::findOrFail(54);
$users = User::whereNotIn('id', $hospital->users()->lists('user_id'))
->lists('email', 'id');
I hope my example helps. What I've done here is selected all of my users which are not in the hospital_user pivot table for the specific hospital.

User roster, joining a table but loosing data

I need some help with a query (using Laravel framework). I'm building a user roster with a few columns that incude the users ratings. Basically, it selects all the active users who have initials and joins the user ratings table to select the ratings for the respective users. The where_in is to select only specific ratings. My issue is on the roster, it only selects one rating, rather than all of them (if the user has more than one rating). I've also tried without the group_by, but then the users are duplicated on the table depending on the number of ratings they have (example: if the user has 2 ratings, their row is displayed twice on the roster).
Query:
$users = DB::table('users')
->where('users.initials', '!=', '')
->left_join('user_ratings', 'user_ratings.uid', '=', 'users.uid')
->where_in('users_ratings.rid', array(6,17,21,20))
->group_by('users.uid')
->order_by('users.name')
->get();
Tables:
Users
=======
uid name
1 John
2 Jeff
3 Cathy
Ratings
======
rid uid
1 1
2 1
2 2
3 1
4 3
The problem is when you do a left_join, the result you are going to get is multiple rows. So without the group_by clause it will return all the results you want in rows, not columns, and with the group_by it will just return the first rating (which is the expected behavior).
I would suggest you just use Eloquent ORM and set up the models and their relationships (it's a lot easier and cleaner). I'm guessing user_rating is a many-to-many pivot table? In which case you would have two models User and Rating and their relationship will be has_many_and_belongs_to. Also, the naming conventions in laravel have the pivot table in alphabetical order, so it will be called "rating_user". Look here for how to set up relationships: http://laravel.com/docs/database/eloquent#relationships
Once the models with their relationships are setup, what I would do is
$users = User::where('initials', '!=', '')->order_by('name')->get();
Then,
foreach($users as $user) {
echo "Ratings for " .$user->name . ": ";
$ratings = $user->ratings()->pivot()->where_in('rid', array(6,17,21,20))->get();
foreach($ratings as $rating) {
however you want to display the ratings here...
}
}
This may not be the most efficient way, but it should get the job done given my assumptions are true.
A quick look at the documentation reveals that the Fluent Query Builder can only do what MySQL can do, and MySQL cannot return an array to the client.
Take a look at this question for your alternatives.
If you want Laravel to fetch the ratings for you, you need to build a model.

Categories