Laravel belongsToMany pivot with multiple columns - laravel

I currently have two tables in the DB and a pivot table to join them when I need to do a belongsToMany lookup. The basic example is one DB table is 'teams' and the other is 'members'. I can utilize the belongsToMany method on both the team and members model to pull their relationship with each other. A team can have many members, and a member can belong to many teams.
public function teams()
{
return $this->belongsToMany(Team::class);
}
public function members()
{
return $this->belongsToMany(Member::class);
}
Pivot: team_member
team_id | member_id
---------------------
1 | 1
2 | 1
3 | 2
1 | 2
How can I expand on that pivot table to include a type of member for each team? For example, member1 is a leader on team1. member1 is an assistant on team2. member1 is a generic member on team3... and so on. Can I just add a column to that same pivot table? Would it be the membertype_id? How can I relate that to another model/table?

This is pretty common, and Laravel handles it already. Add extra columns to the pivot table and expand your relationships to use withPivot():
public function teams(){
return $this->belongsToMany(Team::class)->withPivot(["teamRole", ...]);
}
Then accessing is as simple as:
$user = \App\User::with(["teams"])->first();
$team = $user->teams->first();
$teamRole = $team->pivot->teamRole;
See the Documentation for more information:
https://laravel.com/docs/5.6/eloquent-relationships
To answer the second part, which is essentially a "Triple Pivot", that requires extra functionality. See
Laravel - Pivot table for three models - how to insert related models?
for more information, and an associated Package (by the answerer on that question, not maintained, but good for an example)
https://github.com/jarektkaczyk/Eloquent-triple-pivot

Related

Retrieve values from related table foreign key using Eloquent

Sorry if the question isn't clear.. I'm not super fluent in databases.
I have three tables:
companies equipment parts
----------- ----------- -----------
id id id
name company_id equipment_id
Using Eloquent, how do I get a Collection of all the parts that belong to the company with id=1
I know you setup relationships in the model. So now I can get all a company's equipment ($myCompany->equipment), and all equipment's parts ($myEquipment->parts), but I'm not sure how to easily get values in the reverse direction two tables away.
Thanks!
Laravel has such a beautiful documentation and API for this very thing. Take a look at the hasManyThrough relationship.
So in your Company model add this:
/**
* Get all of the parts for the company.
*/
public function parts()
{
return $this->hasManyThrough('App\Part', 'App\Equipment');
}

Get back data from the pivot table when store a many-to-many relationship

I have a many-to-many relationship between projects and surveys. I can successfully create a relationship between a survey and a project with
$userSurvey = $project->surveys()->save($survey);.
This will create a new record inside the question_survey pivot table (The pivot table contains the columns id, question_id and survey_id.)
$userSurvey will receive the newly created survey model. Is there any way to receive also the id of the new record in the question_survey pivot table?
When retrieving many to many relationships, Laravel will automatically attach the pivot to the resulting Model, so in your case, $userSurvey will automatically have an attribute called pivot that holds, well, of course, the pivot.
But by default, that pivot attribute only holds the foreign keys, so in your case, the question_id and survey_id. If you have any other extra attributes,(in your case id), simply use the withPivot method, as follows.
public function surveys()
{
return $this->belongsToMany('App\Question', 'question_survey')
->withPivot('id');
}
Now you can access the id from the pivot table:
$userSurvey->pivot->id;
Bonus, if you think that the pivot word just does not fit your wording style, just use the as method in your relationship to customize the variable name of the pivot attribute.
public function surveys()
{
return $this->belongsToMany('App\Question', 'question_survey')
->as('question_survey')
->withPivot('id');
}
Now you can access the id from the pivot table:
$userSurvey->question_survey->id;

How to add multiple conditions on Laravel elequent relationship

I am new to Laravel and working on 5.4 version. I have a model "A" and model "B". Model A has hasMany relationship with B. Upto here things are ok. But now, I want to add more conditions on this relationship.
By default, Laravel works only foreign key relation. I mean it matches data on the basis of only 1 condition. Here, I want more condition.
Below are the tables of both Model:
table: A
id name Year
1 ABC 2016
2 DEF 2017
table: B
id A_id name Year
1 1 tst 2016
2 2 fdf 2017
3 1 kjg 2017
By default, If I want to see records of A_id 1 from table B, then Laravel will fetch all records for A_id 1. But now, suppose, if I want to get records for 2016 then How I can I do this using Laravel relationship method?
Below are the Elequent Model for both tables:
class A extends Model{
public function b(){
return this->hasMany('B');
}
}
class B extends Model{
public function a(){
return $this->belongsTo('A');
}
}
Code to fetch records of id 1:
$data = A::with('b')->find(1)->toArray();
The above request is giving me all data from table B for id 1 but I also want to put corresponding year condition also.
Is anyone know, Ho can I do this? Please share your solutions.
Thanks
You have to constrain your eager loads, using an array as the parameter for with(), using the relationship name as the key, and a closure as the value:
$data = A::with([
'b' => function ($query) {
$query->where('year', '=', '2016');
},
])->find(1)->toArray();
The closure automatically gets injected an instance of the Query Builder, which allows you to filter your eager loaded model.
The corresponding section in the official documentation: https://laravel.com/docs/5.4/eloquent-relationships#constraining-eager-loads

Trying to achieve a hasManyThrough type relationship

I'm trying to achieve something that is similar to Laravel's hasManyThrough, but I'm not sure my DB is set up appropriately or I'm just missing something.
I am trying to display a page for admins to show all of the sites we support. I would like to have a simple column that shows a distinct count of how many customers are attached to each site. To do this, I was going to go through the orders table and retrieve a distinct list of users, then simply use the ->count() method inside my view.
Here is my DB setup (simplified):
sites table (primary key: 'id'):
id | ...
users table (primary key: 'id'):
id | first_name | last_name | ...
orders table (primary key: 'order'):
id | order | user_id | site_id | ....
Site model:
public function customers()
{
return $this->hasManyThrough('App\User', 'App\Order', 'site_id', ' id')->distinct();
}
I realize right away that the key difference between my DB setup and the documentation is I do not have an order_id in my users table, but it doesn't make sense that I do since a user can have many orders.
It is worth noting: I also have a table user_orders. I'm not sure if I should be using that instead. user_orders has the following set up:
id | user_id | order
You can see that it is simply an intermediate table to hold connections between users and orders (remember order is the PK in orders, not id).
So, can anyone help me understand what I am doing wrong?
You could get away with a Join. I give you this sample code to guide you
public function customers()
{
return $this->hasMany('App\Order')
->leftjoin('users', 'users.id', 'orders.user_id')
->groupBy('users.id'); //Is this needed?
//Above code will return you a collection of Order though, but with the user data.
//Let's try using the User model
return App\User::whereHas('orders', function($query) use ($this->id) {
$query->where('site_id', $this->id);
})->get();
}

Laravel: get Many-to-Many column data

Yo all,
I have a users relationship pivot db table as follows:
id | user_id | relation_id | relationship
1 4 2 tutor
1 4 3 parent
The table relates user with one-and-other for various reasons.
I am trying to get the relationship column within the $user. I have managed to pull the related users
details no problem - $user->relations.
However, I just need to get the relationship - eg. Tutor or parent.
I am getting no dice with $relative->pivot->relationship
Any ideas? Thanks for taking the time to help.
#foreach($user->relations as $index=>$relative)
{{ $relative->first_name . ' ' . $relative->last_name}}
{{ $relative->pivot->relationship }}
#endforeach
To access ->pivot->whatever you need to add withPivot('whatever') to the relation definition:
public function relations()
{
return $this->belongsToMany('Relation')->withPivot('relationship');
}
Note: I wouldn't use relations and Relation names here, since it's misleading AND it may collide with Eloquent\Model stuff.

Resources