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();
Related
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();
I'm working on a Laravel installation where I have (among other things)
Teachers (table:users (cols: id, name, type), model:User, users.type = 2)
Students (table:users (id, name, type), model:User, users.type = 1)
Schools (table:schools (id, name), model:School)
Collections of students (table:student_collection (id, name), model:StudentCollection)
& table student_collections_users for linking the student-users to collections (model: StudentsCollections, columns id, user_id, collection_id)
I have managed to setup some relationships, but can't get my head around to get
Which teachers teach a student
Which collections does a student belong to
Currently I'm trying to get the collections with
//User.php
public function collections() {
$collection = $this->hasManyThrough('\App\StudentsCollections', '\App\User', 'id', 'user_id');
return $collection;
}
//Controller
$user = \App\User::find($id);
$user->collections = $user->collections();
but it only returns the id's of the collections. How can I get the full data object for each collection?
I'm using Laravel 5.3.
First, In your example code, are the table names correct?
I see a table called 'students_collections', but your belongsToMany has a table name (second param) 'student_collections_users'. That's a typo, I presume.
Second, what does return an empty result? Calling the collections method or the collections property on the User model? Can you add some sample code?
Third: you have actual data in the database (through a seeder or real data)? I know this is obvious, but sometimes people tend to forget the obvious... :-)
In laravel, is there a way to get the list of objects that belong to two models?
For example,
Model transactions:
belongs to users
belongs to category
Model user:
has many transactions
Model category:
has many transactions
Assuming these relationships are correctly defined, what kind of query would you make in, say the controller, to access the set of transactions that belongs to user x and category y?
Assuming that your Transaction table has the foreign keys for user_id and category_id, you could do:
$transactions = Transaction::where('user_id', '=', 'x')
->where('category_id ', '=', 'y')
->get();
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();
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.