Bios90
Bios90

Reputation: 811

Laravel hasMany relationship detach all

Is there a simple solution to detach (without deleting) all related models through a hasMany Relation on a model?

For example, I have two tables:

In the College model I define this relationship:

class College extends Model
{
    public function students()
    {
        return $this->hasMany('App\Student','college_id','id');
    }
}

What is the best way to detach all current College students from the College (i.e, get all the students of the college and set their college_id to null)?

Is there an easy way to detach all students from the College model using eloquent?

Something like

class College extends Model
{
    ...
    public function detachAllStudents()
    {
        ...
    }
}

P.S. already have read this question Laravel hasMany detach, but get errors when I try to apply it to my application

Upvotes: 10

Views: 20083

Answers (3)

Alessandro Benoit
Alessandro Benoit

Reputation: 913

Despite Imran answer perfectly fits this scenario I would add a more generic approach. Let's say $college respects an interface instead of an implementation, you wouldn't know the foreign key at run time.

<?php

use Illuminate\Database\Eloquent\Relations\HasMany;

interface HasStudents {
    public function students(): HasMany;
}

class College extends Model implements HasStudents
{
    public function students(): HasMany;
    {
        return $this->hasMany(Student::class, 'college_id', 'id');
    }
}

function detachStudents(HasStudents $model): void {
    $studentsRelationship = $model->students();
    $studentsRelationship->update([
        $studentsRelationship->getQualifiedForeignKeyName() => null
    ]);
}

detachStudents($college);

Upvotes: 0

Imran
Imran

Reputation: 4750

Yes, you can detach all the college students as below. Actually, we already have the college_id in your students table and we have to make this college_id null somehow. This is not called detach in Eloquent. The word detach come when you have many to many relationships. So, let's just update the students and see if it works or not.

$college->students()->update(['college_id' => null);

So, you method can be completed as below:

public function detachAllStudents()
{
    $college->students()->update(['college_id' => null]);
}

That's it!

Upvotes: 20

Jorge Pe&#241;a
Jorge Pe&#241;a

Reputation: 487

Directly from the documentation https://laravel.com/docs/5.8/eloquent-relationships:

Toggling Associations

The many-to-many relationship also provides a toggle method which "toggles" the attachment status of the given IDs. If the given ID is currently attached, it will be detached. Likewise, if it is currently detached, it will be attached:

$user->roles()->toggle([1, 2, 3]);

Upvotes: 0

Related Questions