Check if the user is attached or not yet - php

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

Related

Laravel insert into many to many relation table [duplicate]

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.

Insert model unless it exists and attach it

I'm a Laravel noob rewriting some old code to Laravel.
I have a system for managing purchases and games and I'm writing the store method of the PurchaseController. The form for creating new purchases contains data about the purchase and an array with data about the games.
There is a many-to-many relationship between games and purchases: a purchase can contain many games and a game may be linked to multiple purchases.
The thing is that the game may already exist in the database. I want to do the following:
Insert the new purchase into the database (this part I got sorted out already ;))
Check if the POSTed name of the game already exists in the database.
If it exists, attach it to the newly inserted purchase. If it doesn't exist, insert it and attach it to the newly inserted purchase.
I don't want to update the game if it already exists in the database, just to attach it to the purchase.
I've looked into firstOrCreate but that doesn't do what I want. It checks on all the arguments you feed it, you can't just make it check only the name (this issue basically).
The undocumented method updateOrCreate does accept two arrays (one for attributes to check on, another for values to insert) but it updates the record if it exists, which is not what I want.
So, is there a nice, proper way to do this with Eloquent or do I simply need to manually write some code that checks if the game exists in the database and inserts the game unless that's the case?
EDIT:
It seems that this is possible with firstOrCreate after all in Laravel 5.3: https://github.com/laravel/framework/pull/13236
firstOrCreate is what you need, but you can feed it just the game name, then attach it to your purchase.
$game = Game::firstOrCreate(['name' => $gameName]);
$purchase = new Purchase(['otherArgs' => ...]);
$purchase->games()->attach($game);
I was probably overthinking this too much. The following code does what I want:
// Insert games (unless they exist) and attach to new purchase
foreach($request->games as $game) {
$gameModel = Game::firstOrNew(['name' => $game['name']]);
if(!$gameModel->exists) {
$gameModel->status_id = $game['status'];
$gameModel->note = $game['note'];
$gameModel->save();
}
$gameModel->purchases()->attach($purchase->id);
}
I just thought maybe there was a nicer/shorter way to do this.

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.

laravel many to many delete and update

I have many to many relationship .
in the blade code i sent many items with actionID[]
and then i insert them like this:
$detailsAttribute->actions()->sync(Input::get('action_id'));
now I want to update that model.
i used this same statement
$detailsAttribute->actions()->sync(Input::get('action_id'));
it creates the new actions but didn't remove the older ones. In other words, when I edit the model $detailsAttribute, I delete the older actions and I select many new ones.
my question is how to update the model considering removing the non selected actions?
sync() method will remove all those items from pivot table if they are not present in your
Input::get('action_id') array. If they are not removed that means you are also passing old data in the new array. var_dump your Input and see what kind of array you are getting.

CodeIgniter: datamapper ORM delete() a relation;

I have a tables called users, countries, and countries_users.
The documentation states that to delete a simple relationship you perform:
// Get user foo
$u = new User();
$u->where('username', 'foo')->get();
// Get country object for Australia
$c = new Country();
$c->where('name', 'Australia')->get();
// Delete relation between user foo and country Australia
$u->delete($c);
This would remove the corresponding row from the countries_users table.
My question is, what if I have no relevant Country() object to construct?
If countries and users are a one-to-many relationship, then certainly knowing the username attribute is enough to disassociate him with a country.
All the delete functions seem to require at least two objects... What is the best way to accomplish the deletion of this type of relation using the DataMapper ORM functions?
"All the delete functions seem to require at least two objects"
Not totally true, a delete() can be preformed on a single object without the need to explicitly delete the object's relationships, it is handled automatically.
From the user guide:
Note: When you delete an object, all its relations to other objects will also be deleted. Free house cleaning! :)
In addition, you may use a column in the users table for the country id instead of a separate countries_users table for relationships, assuming it is a one(country)-to-many(users) relationship.
My question is, what if I have no relevant Country() object to construct?
Then you don't have to worry about anything. If there are no relationships to delete, attempting to delete them will not cause any harm.
There is a relationship to delete! I want to pass the user_id into my Controller and disassociate him with a country in the countries_users table. To accomplish this using the documented functions, I would have to also pass in the country_id... Which IMO is irrelevant for this operation.
You don't have to look up the country id unless you specifically want to delete a particular relationship. In your case, you're working with a relationship where a user can only have one country, so you don't need to specify which related country to delete. Here are two options off the top of my head:
Assigning a new country (removes the previous one)
$c = new Country();
// Get all countries named "Wonderland"
// Usually we'll use an id instead, there could theoretically be more than one
$c->where('name', 'Wonderland')->get();
$user->save($c);
Just delete all related countries (there is only one of course)
$c = new Country();
// Get all countries
$c->get();
$user->delete($c); // You may need $c->all here
If we were working with a many to many relationship, you would of course have to know which ones to delete, but since there is only one - deleting them all is sufficient.
Believe it or not, I was unable to remove the relationship using the code Wesley has provided.
However, this seemed to work:
$u = new User();
$u->where('id', $id)->include_related('country', 'id', TRUE, TRUE)->get();
$c = new Country();
$c->where('id', $u->country->id)->get();
$c->delete($u);

Categories