Laravel & relationships - laravel

I am building a web app using Laravel (5.7). At some point, the user must input his location that is comprised of:
Country
State
City
So for this, I created 4 tables:
Countries table:
Columns: id, name
Relations: hasMany states
States table:
Columns: id, country_id, name
Relations: hasMany cities, belongsTo country
Cities table:
Columns: id, state_id , name
Relations: hasMany Locations, belongsTo state
Locations table:
Columns: id, city_id, name
Relations: belongsTo City
My questions are:
1) Is this the correct approach?
2) Obviously, there are countries out there without the "state" segmentation. If this is the case, how are we going to move up to the Country (using relationships) when the state is not present?
3) How do we know the minimum Eloquent relationships we can use on each model? Because a country also has a lot of cities. Do we use this relationship as well, or is it OK because states has a lot of cities?
I would be very happy if someone helped me clear this out. Its been bothering me for quite some time.
Thanks in advance.

Related

Why Laravel does not make lots of queries when using exists on relations?

I have such entities as:
Company
Person
Company hasMany Persons. So in the persons table there is company_id column.
I return company list, which I pass to CompanyResource. There I return has_persons => $this->persons()->exists() value.
Then I checked the result of DB::getQueryLog() and I found out that there is only one SQL query, which does not have count or anything like that.
In order to count how many persons a company has, Laravel should make one query per company, shouldn't it? Like select count (*) from persons where company_id = 5 for example
try this
$this->persons->count()

Is it possible to join eloquent relationship query?

I have a users, departments, and positions table.
I want to select one department with all the users in that department with their position name.
Currently, I have this.
$department = DepartmentView::with('users')
->findOrFail($departmentId);
It returns me a department with users, but I want to join the users with positions table so I can also get the position name. (user table only has position id)
Assuming you have your relationships setup properly in your User model and the relationship is called position, it should be like this:
$department = DepartmentView::with('users.position')
->findOrFail($departmentId);
Look at eager loading -> nested eager loading.
You can do
$department = DepartmentView::with('users.position')->findOrFail($departmentId)
position is referred to the relationship set on the User model to get the user position.

Query on eloquent relationship

I have Book and Store models which have belongsToMany relationship.
In Book.php
public function stores(){
return $this->belongsToMany('App\Store')->withPivot('qty');
}
In Store.php
public function books(){
return $this->belongsToMany('App\Book')->withPivot('qty');
}
Now I just want to know the total number of books in store A and B together. How can I do it with eloquent ORM? I can get all books belonging to store A and B using whereHas but cannot go further to aggregate the qty field in the pivot table.
So you want the total qty of books by combination of store id and book id
The way you've described your DB structure, it looks like your pivot table has exactly these columns: book_id, store_id and qty
So all you really need to do is:
DB::table('book_stores')->get()

save multiple inputs in middle table with same name Laravel

I am allowing users to add multiple subjects on the fly while adding a student, for example when you are adding a student you can add a subject i.e Math then you will set its attributes teacher name, credit hours etc. But when saving to db I need to save the information to my middle table students_subjects
id | student_id | subject_id | teacher_name | credit_hours
The problem is that how I can save the information for each subject. I can save the subject_id in a hidden field and get that but how would I know that this id is related to that particular subject and get the teacher and credit hours for that id.
how I can save the information for each subject
DB::table('students_subjects')->insert([
'student_id' => $input['studentId'],
'subject_id' => $input['subjectId'],
'teacher_name' => $input['teacherName'],
'credit_hours' => $input['creditHours'],
]);
I can save the subject_id in a hidden field and get that but how would I know that this id is related to that particular subject
If you have the subject_id - then you know what subject it relates to.
get the teacher and credit hours for that id
$result = DB::table('students_subjects')
->select(['teacher_name', 'credit_hours'])
->where('id', $id)
->first();
So you have 3 tables. And a many-many relationship
students
subjects
student_subject
Take a look at https://laravel.com/docs/5.2/eloquent-relationships#many-to-many to learn about defining your eloquent models.
From your question, I would consider changing how you structure your database.
A student hasMany subjects. A subject belongsTo teacher.
So I would have 4 tables as follows:
students
- id
- first_name
- last_name
student_subject
- student_id
- subject_id
- credit_hours (assuming this is the number of hours the student has studied?)
subjects
- id
- name
- credit_hours (assuming this is the total credit value)
teachers
- id
- name
- subject_id
If a teacher can teach many subjects, then you would need to add a subject_teacher pivot table.
When adding the student, if you could provide a dropdown list of subjects whose value is the subject_id, then when you select the subject - you post the subject_id back to php ready to insert into the DB.

Eloquent Subquery

I have a many to many relationship between a student table and a apparatus table (A student performs on many apparatuses and an apparatus has many students). I have a student_results table that has a composite primary key (student_id and apparatus_id) and a 3rd field called results).
I have written a query to find all the apparatuses that a student DOES NOT have a result. The example I give is for student with id = 121.
The sub-query is.
SELECT apparatus_id, strapparatus_name FROM apparatuss
WHERE apparatus_id <> ALL(SELECT apparatus_id FROM student_results
WHERE student_id =' . 121 . ')';
I would like to write this using Eloquent (Laravel 4.1).
Any help greatly appreciated.
Assuming that you already have your Eloquent models Apparatus and StudentResult set, this is a way:
Apparatus::whereNotIn(
'apparatus_id',
StudentResult::where('student_id', 121)->lists('apparatus_id')
)->get('apparatus_id', 'strapparatus_name');
Or, if you don't have a model for your student_results table, you can just:
Apparatus::whereNotIn(
'apparatus_id',
DB::table('student_results')->where('student_id', 121)->lists('apparatus_id');
)->get(array('apparatus_id', 'strapparatus_name'));

Resources