Delete one entry from pivot table laravel - laravel

How can i delete only one entry from many-to-many relationship pivot table in laravel if i have the id of the row?

Solved it. I used:
->wherePivot('id', '=', $pivot_id)->detach()
and it worked great.

Suppose you have User & Entity models with many-to-many relationship. Then you could use
$user->entity()->detach($entityId);
That will only delete the row with that $entityId

The best practice you can do it like this,
// Detach a single entity from the user...
$entity = Entity::find($your_entity_id);
$user->entities()->detach($entity->id);
First, find the entity with your desired id by Entity Model,
$entity = Entity::find($your_entity_id);
After you will get entity, you can pass it into detach() method,
$user->entities()->detach($entity->id);
For more information go through this link.

Related

Additional conditions on a belongsToMany relation on the intermediate table

When using the belongsToMany relation in Laravel Eloquent, is it possible to add additional conditions for the intermediate table? Currently, the inserts are duplicating and I am just trying to understand how to fix it.
Here is the relation
Models/Order.php
public function addresses(): BelongsToMany
{
return $this->belongsToMany(CustomerAddress::class)
->withPivot('address_type')
->withTimestamps();
}
Here is how I save the data to the intermediate table
$tenantOrder-addresses()->attach($customerAddress->id, [
'address_type' => 'billing'
]);
Do I need to do anything else to prevent the duplicates? Below is the example of showing the duplicates. The combination being customer_address_id, order_id, address_type.
I did take a look at Eloquent belongsToMany relation with additional conditions, but this doesn't help with the resolution.
If you mean to prevent duplicate on pivot table, can add composite keys on pivot table migrations
Something like this
...
$table->primary(['customer_address_id', 'order_id', 'address_type']);
That will prevent adding new row if the customer, order, and address type in a same value.
Here's a test
Docs
I believe you are looking for syncWithoutDetaching. It helps attach without duplicated record.
Reference: https://laravel.com/docs/9.x/eloquent-relationships#syncing-associations

Model doesn't show up on relationship right after saving?

For example
$user->transactions()->save($transaction);
dump($transaction->id); // id: 4
dd($user->transactions); // last id is 3
The $transaction that is saved does not show up in $user->transactions. This is a polymorphic relationship.
When you save a model through a relationship, all Laravel does is set the appropriate foreign keys. It doesn't set the newly saved model to the relation or add it to a collection.
If you want the model with updated relations use the fresh function.
$user->transactions()->save($transaction);
$user = $user->fresh('transactions');
Edit answer updated following #JCLee's correction to assign the result of $user->fresh().

Laravel how many relationship can be chained

I have a database composed by users, users_child, child.
I create a ONE to MANY relationship between Users and users_child, then i create a relationship between users_child and child. Now the below code work:
$test = users::find(1)->users_child
$test1= users_child::find(1)->child
Now i want to know if is possible to create a single row that link the three table like this:
$test = users::find(1)->users_child->child
I create the relationship in the model but in the db i don't create Foreign Key, it's a problem? on the model i specify the field for link table.
http://laravel.com/docs/5.1/eloquent-relationships#querying-relations
You can chain relationships like this:
$user = Users::with("users_child.child")->where("id",1)->first();
Each point will mean a relation stored in the first.
Out of users users_child will be taken and out of users_child child will be taken. (Relations)
foreach($user->users_child as $user_child) {
$user_child->child;
}
will get you the data you need.

Updating a pivot table in Eloquent

I've got a many to many relationship between a student and an institution_contact.
students should only ever have two institution_contacts and I have an attribute on the pivot table named type to be set as 1 or 2.
So, my pivot table looks like this:
institution_contact_student: id, institution_contact_id, student_id, type
I've run into difficulty in deciding how to approach the issue of adding/updating the pivot table. Let's say I have 100 students and I want to assign them a contact with the type of 1.
My current solution is to delete the contact then add it:
$students = Student::all(); // the 100 students
$contactId = InstitutionContact::first()->id; // the contact
foreach ($students as $student) {
// remove existing contact
$student
->institutionContacts()
->newPivotStatement()
->where('type', 1)
->delete();
// add new contact
$student
->institutionContacts()
->attach([$contactId => ['type' => 1]]);
}
However, I'm thinking that this is going to hit the database twice for each student, right? So would I be better off creating a model for the pivot table and removing all entries that matched the student id and the type then simply adding the new ones? Or would creating a model for the pivot table be considered bad practice and is there a better way of accomplishing this that I've missed?
Please note the reason I'm not using sync is because I'm relying on the type attribute to maintain only two contacts per student. I'm not aware of a way to modify an existing pivot without causing issues to my two contacts per student requirement.
Edit:
Instead of creating a model I could run the following code to perform the delete using DB.
DB::table('institution_contact_student') // the pivot table
->whereIn('student_id', $studentIds)
->where('type', 1)
->delete();
If I have understood your question correctly then you can use the updateExistingPivot method for updating your pivot table.But first of course you have to define the pivot in your relationship. For instance,
public function institutionContacts(){
return $this->belongsToMany('institutionContact')->withPivot('type');
}
after this, all you have to do is use the following code:
$student
->institutionContacts()
->updateExistingPivot($contactId, ["type" => 1]);
Hope this helps.

return separate result for each relation in many to many

Hi i have a many to many relationship with the following structure:
services
apps
service_app
I would like to have an eloquent query to return a separate result for each relationship(basically the pivot table). I have the following :
$all = App::with('services')->get();
this will return an app with nested services, I would like to have this return a separate result for each app-service combination along with data from the pivot table. how is this possible using eloquent?
It's a bit strange, but it can easily be done if you don't think of the pivot table as a pivot table, but as an AppService.
So what you can do is create a model for it, probably named AppService. In that model, you would then have 2 belongsTo() relationships. One for App and one for Service.
Then you can query your pivot table directly and use those relationships to get what you need.
$appServices = AppService::all();
foreach($appServices as $appService) {
echo $appService->app->description;
echo $appService->service->description;
}

Resources