How can I make a relation between tables in Laravel? - php

I have three tables like these:
// users
+----+-----------+
| id | user_name |
+----+-----------+
| 1 | Jack |
| 2 | Peter |
| 3 | John |
+----+-----------+
// skills
+----+------------+
| id | skill_name |
+----+------------+
| 1 | PHP |
| 2 | HTML |
| 3 | Laravel |
| 4 | MySQL |
| 5 | jQuery |
+----+------------+
// skill_user
+----------+---------+
| skill_id | user_id |
+----------+---------+
| 2 | 1 |
| 5 | 1 |
| 1 | 2 |
| 2 | 2 |
| 4 | 2 |
+----------+---------+
Now I want to get all skills of one specific user. I can do that by using a join clause in a raw sql query:
SELECT s.skill_name
FROM skills s
JOIN skill_user su ON s.id = su.skill_id
WHERE su.user_id = :user_id
/* output (assuming :user_id is 1)
+------------+
| HTML |
| jQuery |
+------------+
Ok All fine. Now I want to know, how can I do that by adding a method in the model of Laravel framework? All I'm trying to do is using belongsTo(), hasOne(), hasMany() etc ..

To do in Eloquent way, you need to add the relationship. In your case, it is many-to-many relationship so in User.php, add this function to declare the relationship:
public function skills() {
$this->belongsToMany(\App\Skill::class, 'skill_user', 'user_id', 'skill_id');
}
Then,
Access it like this to eager load it:
$users = \App\User::with('skills')->get();
OR
Say you have a single user,
$user = User::where('id', 1)->first(); // Get the user with id = 1
and to get the skill for that user:
$user->skills;
OR
If you don't want to do using Eloquent way, you can use Query Builder. Note that, using this method, you basically join it manually so you don;t need to add any method to the Model:
\DB::table('users')
->join('skill_user', 'skill_user.user_id','=', 'users.id')
->join('skills', 'skill_user.skill_id', '=', 'skills.id')
->select('*')
->where('users.id', 1)
->get();

You have to use belongsToMany relationships. Assuming you will create SkillUser model for skill_user table. Add the following code to User Model
public function skills() {
$this->belongsToMany('App\SkillUser', 'skill_user', 'user_id', 'skill_id');
}
Now you can access it by
$users->skills();

I assume you are talking about Many to Many relationship between Users and skills, then the example given in Laravel many-to-many speaks about it.

Related

Laravel Eloquent multiple relationship in a football game schedule

I am new to Laravel and Eloquent and i am trying to create a football game plan.
For now i have 4 tables (with some example entries):
teams (all teams)
+---------+-----------+
| team_id | team_name |
+---------+-----------+
| 1 | Arsenal |
| 2 | Chelsea |
+---------+-----------+
competition (all competitions)
+----------------+------------------+
| competition_id | competition_name |
+----------------+------------------+
| 1 | Premier League |
+----------------+------------------+
schedule (schedule to the competitions)
+----+----------------+----------+--------------+--------------+-----------+-----------+
| id | competition_id | matchday | home_team_id | away_team_id | home_goal | away_goal |
+----+----------------+----------+--------------+--------------+-----------+-----------+
| 1 | 1 | 1 | 1 | 2 | 3 | 2 |
| 2 | 1 | 2 | 2 | 1 | 0 | 3 |
+----+----------------+----------+--------------+--------------+-----------+-----------+
schedule_teams (matches the schedule teamid with the teams id over the competition_id and the schedule_team_id)
+----+------------------+----------------+----------+
| id | schedule_team_id | competition_id | teams_id |
+----+------------------+----------------+----------+
| 1 | 1 | 1 | 1 |
| 2 | 2 | 1 | 2 |
+----+------------------+----------------+----------+
And here are my current classes:
Schedule.php
public function competition()
{
return $this->belongsTo(Competition::class, 'competition_id', 'competition_id');
}
Competition.php
public function schedule()
{
return $this->hasMany(Schedule::class, 'competition_id', 'competition_id');
}
With
$id = \request('competition_id');
$schedule = Schedule::where('competition_id', $id)->with('competition')->get();
i get the schedule with the home and away id's from schedule.
The question now is, how can i get the entries from the teams table over the schedule_teams table to a specifiy home and away id, also for example home_team_id = 1:
home_team_id (=1) -> schedule_team_id (=1) and competition_id (=1) -> teams (Arsenal)
I want the data from schedule and the associated teams in a collection to output in a blade.
can anyone help or give me improvement tips for a football database?
You should make use of the hasManyThrough relationship.
If you create say Schedule\Team, and then have that like the following.
public function schedule() {
$this->belongsTo(Schedule::class, 'schedule_id');
}
public function team() {
$this->belongsTo(Team::class, 'team_id');
}
Now in your Schedule class, you can have the following.
public function teams() {
$this->hasManyThrough(Team::class, Schedule\Team::class, 'schedule_id');
}
It should also be noted, that you don't need competition_id in your schedule team. Since a team belongs to a schedule, which belongs to competition, you can get it like that.
If you also want your Team to know about its schedules, you can add this to Team.
public function schedules() {
return $this->hasManyThrough(Schedule::class, Schedule\Team::class);
}
You Schedule\Team class becomes essentially, a glorified representation of a pivot table, but having it as a model, allows you to expand upon it in the future. It also helps keep everything neat.
Hope that makes sense.

Database inheritance Laravel 5.4

I am looking forward to implement a website dealing with teachers, students and parents. In the database I made, I've created a user table and 3 children tables : teachers, students, parents.
See below the table structure
User table
+--------+----------+----------+-------+
| id (PK)| username | password | email |
+--------+----------+----------+-------+
| 1 | user1 | 123 | ... |
+--------+----------+----------+-------+
| 2 | user2 | 132 | ... |
+--------+----------+----------+-------+
| 3 | user3 | 321 | ... |
+--------+----------+----------+-------+
Student table
+---------------+--------------+
| users_id (PK) | class |
+---------------+--------------+
| 1 | highschool |
+---------------+--------------+
| 3 | middleschool |
+---------------+--------------+
Teacher table
+--------------+-------------------+---------------------+
| users_id (PK)| subscription_type | end_of_subscription |
+--------------+-------------------+---------------------+
| 2 | monthly | 2017-10-25 |
+--------------+-------------------+---------------------+
And the parents table also have a PK which corresponds to a user id.
I just started to learn laravel and I really wonder how could I handle this properly maybe with eloquent with Laravel 5.4.
I am giving you some hints I think you can do rest and as your question is not specific I am guessing you are thinking how can you relate/join tables, so
Create three model let say User, Student, Teacher.
In Student & Teacher model create a method like below
public function user()
{
return $this->hasOne(User::class, 'id', 'users_id');
}
Now you can query like :
$student = Student::find($id) ;
$name = $student->user->name;
$email = $student->user->email ;
Or
$teachers = Teacher::where('subscription_type', 'monthly')->with(['user'])->get();
dd($teachers);
I think you need to update your database structure, you need pk & fk
column separated.

laravel 5 - Eloquent Relationships (permissions table)

I think am struggling to get the relationships correctly in the scenario I have.
I have three tables
Table: users
| id | username |
----------------------
| 1 | pluto |
|------|-------------|
Table: permissions
| id | user_id | level_id | app_id |
--------------------------------------------------
| 1 | 1 | 2 | 9 |
|------|-------------|--------------|------------|
Table: levels
| id | level |
----------------------
| 1 | admin |
|------|-------------|
| 2 | manager |
|------|-------------|
| 3 | editor |
|------|-------------|
The result I am looking to get is
manager //through User:: model or Auth::
I would like to get a value from levels table in level column either through User model. This is the last version on what I have in my classes...
class User extends Authenticatable
{
public function permissions()
{
return $this->hasOne('App\Permissions');
}
}
class Permissions extends Model
{
public function user()
{
return $this->hasMany('App\User');
}
public function levels()
{
return $this->hasMany('App\Levels');
}
}
class Levels extends Model
{
public function permissions()
{
return $this->belongsTo('Modules\Ecosystem\Entities\permissions');
}
}
Using this in the controller I am able to retrieve values from permissions table. However I am unable to get values from levels table...
$user = User::with('permissions')->find(Auth::user()->id);
However I am unable to get values from levels table when I try this...
$user = User::with('permissions.levels')->find(Auth::user()->id);
That produces an error:
Column not found: 1054 Unknown column 'levels.permissions_id' in 'where clause' (SQL: select * from `levels` where `levels`.`permissions_id` in (1))
I understand that I am not understanding exactly how relationships would work in this instance but I don't want to just guess a solution. I'd like to understand it.
The thing is ,, Levels table serves only as a list of permission levels (roles). I recognize that I can define permission levels in some other way but for the moment this is how everything is set up.
If you are making a usual user permission system, where 'roles' is replaced by 'levels', then you need to reorganized your tables and relationships.
Table: users
| id | username | level_id |
---------------------------------------
| 1 | pluto | 2 |
|------|-------------|----------------|
Table: levels
| id | level |
----------------------
| 1 | admin |
|------|-------------|
| 2 | manager |
|------|-------------|
| 3 | editor |
|------|-------------|
Table: permissions
| id | level_id | app_id |
-----------------------------------
| 1 | 2 | 9 |
|------|-------------|------------|
So now User
hasOne('App\Levels', 'level_id');
Levels
hasMany('Modules\Ecosystem\Entities\permissions', 'level_id');
Permissions
belongsTo('App\Levels', 'level_id');
That is probably what you were trying to do, and it will works.
However, if many roles may have similar permissions, e.g: admin, manager & editor can all have access to a 'Page' or 'Content' or whatever that they all have access to, then you will need a 4th table to have many-to-many relationship between permissions and levels.
Table: permissions
| id | app_id |
---------------------
| 1 | 9 |
|------|------------|
Table: levels_permissions
| level_id | permission_id |
-----------------------------------
| 2 | 1 |
|-------------|-------------------|
With this, in Levels
belongsToMany('Modules\Ecosystem\Entities\permissions', 'levels_permissions', 'level_id', 'permission_id');
Inverse the relation in Permissions
belongsToMany('App\Levels', 'levels_permissions', 'permission_id', 'level_id');
In both approaches, you can now do
$user = User::with('levels.permissions')->find(Auth::user()->id);

How to eager load and query a pivot table using Eloquent - Laravel 5

Situation: A single appointment can be related to many clients and many users, so I have a many-to-many relationship (pivot table) between appointment and client, and another between appointment and user
I'm trying to write the eloquent query to get a client's information, with all its related appointments and the users related to each of those appointments.
Tables
|appointment|
| |
-------------
| id |
| time |
| created_at|
| updated_at|
| client | | appointment_client |
| | | (pivot table) |
------------- ----------------------
| id | | appointment_id |
| name | | client_id |
| created_at| | created_at |
| updated_at| | updated_at |
| user | | appointment_user |
| | | (pivot table) |
------------- ----------------------
| id | | appointment_id |
| name | | user_id |
| created_at| | created_at |
| updated_at| | updated_at |
Appointment.php model
public function client()
{
return $this->belongsToMany('App\Client')->withTimestamps();
}
public function user()
{
return $this->belongsToMany('App\User')->withTimestamps();
}
Client.php model
public function appointment()
{
return $this->belongsToMany('App\Appointment')->withTimestamps();
}
User.php model
public function appointment()
{
return $this->belongsToMany('App\Appointment')->withTimestamps();
}
On the client/id show page, I would like to show the client's information, list all of the appointments related to this client, and get the related user information for each appointment.
Not sure how to get the users related to the appointments with that:
$client = Client::with('appointment')
->where('id', '=', $id)
->firstOrFail();
It should be enough to just do:
$client = Client::with('appointment', 'appointment.user')->findOrFail($id);
This will load the client with given ID, then eager load their appointments and then, for each of the appointments, it will load related users.

Laravel getting results from model belongsToMany relationship back to controller

I'm using Laravel 5 and Eloquent, I have 3 tables setup:
photos
+----+---------------+------------------+
| id | photo_name | photo_location |
+----+---------------+------------------+
| 1 | kittens.jpg | C:\kittens.jpg |
| 2 | puppies.jpg | C:\puppies.jpg |
| 3 | airplanes.jpg | C:\airplanes.jpg |
| 4 | trains.jpg | C:\trains.jpg |
+----+---------------+------------------+
photo_set (pivot table)
+------------+----------+
| set_id | photo_id |
+------------+----------+
| 1 | 1 |
| 1 | 2 |
| 2 | 3 |
| 2 | 4 |
+------------+----------+
sets
+----+----------------+
| id | description |
+----+----------------+
| 1 | cute animals |
| 2 | transportation |
+----+----------------+
I created a belongsToMany relationship in my photos and sets models to link these two together.
class Photo extends Model {
public function sets()
{
return $this->belongsToMany('App\Set');
}
}
and
class Set extends Model {
public function photos()
{
return $this->belongsToMany('App\Photo');
}
}
However I'm trying to reference the $Sets->photos() model function in my controller, so that given a set of id=1, I can return the photo_location value for each row [C:\kittens.jpg,C:\puppies.jpg], but I don't know how to access it..
Also, I can "sort of" access this information in the view with:
#foreach($sets as $set)
{{$set->images}}
#endforeach
but it looks like it only iterates through once and returns a json (?) of the necessary information, though I'm not sure how to parse that to regular HTML either.
So in short, I'm having trouble accessing this data (photo_location) from both the controller and the view
Use Collection::lists()
$locations = Set::find(1)->photos->lists('photo_location');
It will return an array ['C:\kittens.jpg', 'C:\puppies.jpg']
http://laravel.com/api/4.2/Illuminate/Database/Eloquent/Collection.html#method_lists
In your controller try this :
$result = PhotoSet::where('set_id', $set_id)
->with('sets')
->with('photos')
->get();
$photo_location = $result->photos->photo_location;
here PhotoSet is the model for photo_set table, because it is a pivot table we will be able to access both sets and photos table from it.

Categories