Laravel insert into many to many relation table [duplicate] - php

A simple and straight one:
How can I attach or detach new records when using a Laravel hasManyThrough relation the Laravel way?
Model retrieving is obvious, from the docs here.
EDIT: In other words, is there a Laravelish way of doing the following smarter (model names taken from docs)?
$user = $country->users()->first;
$post->user_id = $user->id;
$post->save();
Thanks in advance.

hasManyThrough() requires an existing intermediate relationship. In the docs example, User is the intermediate relationship. Directly attaching a Post to a Country is not possible because it doesn't know which User owns it. You need to first attach it to the User.

https://laravel.com/api/5.8/Illuminate/Database/Eloquent/Relations/HasManyThrough.html
Yes, but you have to specify all the params.
firstOrNew
// (Doesn't persist to DB, you have to manually call the save method later on the created model)
updateOrCreate
// (Persists to DB)
rawUpdate
// (Persists to DB, not recommended)
push is supposed to work too, according to the docs.
On a 1:M relationship, there's the save method available out of the box. That's because the only field Laravel has to fill in is the foreign key.
For example, Let's say you've got a Parent and Child models. When you call
$parent->children()->save(new Child(...));
Laravel fills in the foreign key and persists the model
If we had a GrandParent model as well, and we tried to save a child through a HasManyThrough relationship:
$grandparent->grandchildren()
Laravel would not only have to fill in for the Parent foreign key, but maybe even create a new Parent model as well since we're not sure it exists. That's why there's not a save method implemented.
Therefore, you can make something like
$grandparent->grandchildren()->firstOrNew(['parent_id' => $parent_id])->save();
// Or
$grandparent->grandchildren()->updateOrCreate(['parent_id' => $parent_id]);
You need a valid key too or else you'll get a SQL constraint violation.

Related

Check if the user is attached or not yet

I'm working with Laravel on little project, i have a pivot table and I would like to attach new users, but I must check if the user is not already attached. how can I do ?
$user = User::findOrFail(2);
$user->liked()->attach(6);
dd($user);
How can I check if the user number 6 is already attached or not, so i can add the new record.
You may also use the sync method to construct many-to-many associations. The sync method accepts an array of IDs to place on the intermediate table. Any IDs that are not in the given array will be removed from the intermediate table. So, after this operation is complete, only the IDs in the given array will exist in the intermediate table:
$user = User::findOrFail(2);
$user->liked()->sync([6,//ids you want attach]);
dd($user);
If you do not want to detach existing IDs that are missing from the given array, you may use the syncWithoutDetaching method:
$user->liked()->syncWithoutDetaching([1, 2, 3]);
Also Refer This

Laravel many to many with a pivot relationship.

User
uid
Provider
pid
Resolution
rid
ProviderResolution
prid
pid
rid
active
ProviderResolutionUser
prid
uid
class Provider extends Model {
public function resolutions()
{
return $this->belongsToMany('App\Models\Resolution')->withPivot('active')->withTimestamps();
}
}
class Resolution extends Model {
public function providers()
{
return $this->belongsToMany('App\Models\Provider')->withPivot('active')->withTimestamps();
}
}
class User extends Model
{
}
Trying to create a Eloquent relationship with this.
I'm trying to figure out how to fit user into this model. It seems like it's suppose to belongsToMany. Do I need to create a class that represents the pivot?
Then from the case of the User how would I query a list resolutions?
You didn't ask but I personally think it's a lot easier to let the primary key of each table be 'id.' Also, in the case of ProviderResolution, unless you have a specific case for it, you don't need (and shouldn't use) 'prid' at all. Just 'pid', 'rid' and 'active' should be sufficient. The 'pid' and 'rid' make the composite primary key on their own. If you add yet another key ('prid'), then there will be a three-key composite which will technically enable you to have duplicates with your other two primary keys. Yuck. Example: PRID:1, PID:1, RID:1, then PRID:2, PID:1, RID:1. Now you have duplicates but your record is technically still unique because of the PRID key. But, maybe you want it this way for some reason?
For the answer I'm going to assume you are using Laravel 5.4+.
So first off, you don't need a class for the pivot. And secondly, you are currently trying to create a relationship between the user and the existing pivot table between Provider and Resolution by creating a table called 'provider_resolution_user'. If you want to query resolutions for a user, just use the relationship methods which gives you access to the attributes on the pivot table and the related models/tables.
First, setup the 'hasMany' relationships in both classes: Users and Resolutions (Providers already has a relationship to Resolutions, so you can use that relationship if you want to see the related Provider.) Then you'll need a pivot table called 'resolution_user'. Put the 'uid' and the 'rid' in the table. Make the relationships to the corresponding foreign key fields to their parent tables.
Now you can access the relationship directly like:
$user->resolutions->rid (or whatever the attribute is you want)
The previous example assumes you have already created a way to insert records into the pivot table (resolution_user) that relate the user and the resolution together.
If you want to access one of the attributes on the pivot table, 'pivot' creates an object instance with it's own attributes (from the table). You can access it like this:
$user->resolutions->pivot->active;
Of course, these methods are chainable so if you just wanted to see the active resolutions, you could also add a ->where statement.
Hope that helps and wasn't too muddy. I'm happy to clarify any points if need be.
EDITED ANSWER:
Because what you want to do is to disable a row in the provider_resolution table and have that reflect on the correct user, then just create a relationship in both the User model and the Resolution model. So when you disable a row in provider_resolution (pid, rid, active), you can lookup the appropriate user to update by using the inverse relationship between resolution and user. This should give you the user that is assigned to that particular resolution/provider combination. If for some reason you do need to find the user based on a unique combination of the TWO: resolution AND provider, then we might need to talk about polymorphic relationships. Let me know.

Eloquent relationships syncing

I'm struggling with Eloquent relationships in my Laravel project.
I have a 'user' table and a 'user_lines' table in my database. The 'user_lines' table has a' user_id' field that corresponds to the 'id' field in 'users', in a classic master-detail relationship.
The User model has a hasMany relationship to the UserLine model. The UserLine model has a belongsTo relationship to the User model.
In my application I have a user form that contains several userlines. During form submits those userlines can be added, altered or deleted. So far I find myself iterating the submitted userlines and manually creating, updating and deleting the userlines. I feel I'm missing out on the attach/detach/sync methods Eloquent provides but I can't seem to get them to work.
$user->lines()->attach or $user->lines()->sync
gives me an exception telling me these are undefined methods on Illuminate\Database\Query\Builder.
$user->lines()->createMany($lines)
works but that just creates new lines, it does not update existing lines and delete removed lines.
The attach, detach and sync methods are for the many-to-many relationship and not for one-to-many. So, you need to iterate over lines and add or edit them one by one.
Your tables relationships isone-to-many and for attaching to such relationships you should use save, saveMany or create methods.
for updating you could do something like this:
$user->lines()->where('field',$something)->update($array);
The attach, detach and sync methods are for the many-to-many relationships and not for one-to-many.

Connecting database fields and model attributes in Laravel

I'm just getting going with Laravel, and have used Eloquent to define my Campaign table. I have a Campaign model which is currently empty.
I'm not sure how to add attributes to this model to represent the fields in the db - or even if I should. The Laravel documentation seems thin on models and searches keep leading me to accessors and mutators.
If I have a database field called platform_type in my campaigns table, how do I link the PlatformType model attribute to this field?
To clarify:
This is not a question about relationships - there is only one entity in my solution thus far.
platform_type is a field in my campaigns table because it is an attribute of a campaign - I'm asking how to represent this in my model.
The model has an internal array which stores the attributes of a given row (it's called $attributes and replicated by $original if you look for them in the source code). The reason it's replicated is so when you call save() it will only do a save if you actually changed them from the originals.
You can access said attributes via $modelInstance->getAttribute("platform_type") or $modelInstance->platform_type which will call the magic __get method that in turn calls the getAttribute
So in your case you can have:
$campaign = Campaign::find($id);
echo $campaign->platform_type;
The ORM will automatically create the relevant SQL query and fill the model instance with the attributes of the row it finds.
You need to define relationships. In the PlatformType model:
public function campaigns()
{
return $this->hasMany(Campaign::class, 'platform_type');
}
And in the Campaign model:
public function platformType()
{
return $this->belongsTo(PlatformType::class, 'platform_type');
}
You also need to rename the campaign table to campaigns. Or you should add this to the model to be able to use a custom name:
protected $table = 'campaign';
At this point, these tables will be connected and relationships will work. However, it is recommended to add foreign key constraints.

How to retrieve data from additional columns in a pivot table and also be able to update it in laravel 5.2

I was working on making a group functionality for my website which uses a many to many relationship between groups and users.
My User model looks like this:
public function groups(){
return $this->belongsToMany('App\Group')->withPivot('role')->withTimestamps();
}
My Groups model looks like this:
public function users(){
return $this->belongsToMany('App\User')->withPivot('role')->withTimestamps();
}
So my third column has the name of role which is a string variable and is set to a default of "member" for members of my group and I set it to "admin" for the actual user who creates a new group. But I want the admin to have the option of making multiple members admins as well which would require me to check weather the current current user who sent the request is an admin or not. If he is, then I wanna be able to take his request of making a member an admin which would require me to update the role for that particular "member" to an "admin".
In the laravel documentation it only shows you how to attach and detach data in a pivot table and else where I have only seen methods of retrieving data from the first two columns but how can I do the same for additional columns and also be able to update it using the updateExistingPivot method?
You could access the column simply using pivot e.g :
$user->pivot->role
Take a look at Retrieving Intermediate Table Columns in documentation Eloquent Relationships.
Hope this helps.

Categories