Relazione molti a molti in un modello dati con Laravel Eloquent ORM
Nella modellazione dei dati Entity Relationship
, esiste una relazione molti a molti quando più record in un’entità possono essere associati a più record in un’altra entità e viceversa.
Questo tipo di relazione è rappresentato utilizzando una tabella di join
che include chiavi esterne che fanno riferimento alle chiavi primarie delle entità correlate.
Vediamo come eloquent
di laravel
ci aiuta nella gestione della relazione molti a molti, semplificandone le query
.
Tempo di lettura stimato: 5 minuti
Relazione Molti a Molti
Una relazione molti a molti non è una proprietà dei dati stessi, ma della relazione tra le tabelle. Garantisce che ogni riga di una tabella corrisponda a più di una riga di un’altra tabella, e viceversa.
È una rappresentazione dell’associazione tra due entità in cui un’entità (il lato “molti-uno”) può essere collegata a più istanze di un’altra entità (il lato “molti-due”), e ciascuna istanza sul lato “molti-due” può essere collegata a più istanze dell’entità sul lato “molti-uno”.
Se vuoi approfondire il caso della relazione uno a molti con eloquent
di Laravel
, allora leggi questo articolo Relazione uno a molti in un modello dati con Laravel Eloquent ORM
Consideriamo ad esempio le entità Studente e Corso. Una relazione molti a molti tra queste due entità significherebbe che: Un singolo studente può iscriversi a più corsi. Ad un singolo corso possono essere iscritti più studenti.
Per implementarlo in un database, dovremmo creare una tabella di join, spesso chiamata tabella associativa o di giunzione, che potrebbe essere denominata Studet_Subject. Questa tabella avrà almeno due campi: Student_Id
e Subject_Id
. Ogni record nella tabella Studet_Subject
rappresenta un collegamento tra uno studente e un corso, indicando che lo studente è iscritto a quel corso.
Laravel Eloquent
Relazione Molti a Molti
Laravel Eloquent
fornisce metodi completi per gestire le relazioni tra le tabelle del database. In questo articolo vedremo la relazione molti a molti, e come impostarla.
In una relazione molti a molti, un’entità (chiamiamola A) può essere associata a più istanze di un’altra entità (chiamiamola B). Allo stesso modo, ciascuna istanza di B appartiene a più istanze di A.
Ad esempio, consideriamo uno scenario in cui:
- uno studente ha più materie da studiare, e
- ogni singola materia può essere studiata da più studenti.
Creazione Tabelle con Migration di Laravel
Creiamo le tabelle del database necessarie per gli studenti, le materie e la tabella pivot student_subject
. Possiamo utilizzare le migration
di Laravel
per creare queste tabelle. Ecco come:
// Create the 'students' table
Schema::create('students', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
// Create the 'subjects' table
Schema::create('subjects', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
// Create the 'student_subject' pivot table
Schema::create('student_subject', function (Blueprint $table) {
$table->id();
$table->foreignId('student_id');
$table->foreignId('subject_id');
$table->string('grade')->nullable();
$table->timestamps();
});
Eseguiamo le migrations utilizzando il comando di linea php artisan migrate
.
Impostazione relazione Molti a molti
Definiamo le relazioni nei modelli Student
e Subject
, usiamo i comandi Artisan
php artisan make:model Student
php artisan make:model Subject
Modifichiamo il file Student.php
con il metodo belongsToMany
// app/Models/Student.php
class Student extends Model
{
public function subjects()
{
return $this->belongsToMany(Subject::class);
}
}
Modifichiamo il file Subject.php
con il metodo belongsToMany
// app/Models/Subject.php
class Subject extends Model
{
public function students()
{
return $this->belongsToMany(Student::class);
}
}
Esempio CRUD uno a molti
Inserire
Creiamo il metodo store_subject
nel controller StudentController.php
per creare le materie per uno studente. Supponiamo che il metodo store_subject
ha due parametri: il nome dello studente e le sue materie:
// app/Http/Controllers/StudentController.php
//
// $name: student
// $subject: array
public function store_subject(string $name, array $subjects)
{
$student = new Student;
$student->name = $name;
$student->save();
// Create subjects
// $subjects = ['English', 'Math', 'Science'];
foreach ($subjects as $subjectName) {
$subject = new Subject;
$subject->name = $subjectName;
$subject->save();
// Attach the subject to the student
$student->subjects()->attach($subject->id);
}
return "Subjects created for student: {$student->id}";
}
Leggere
Per leggere le materie associate a uno studente
public function getsubjects(int $id_student)
{
$student = Student::find($id_student);
$associatedSubjects = $student->subjects;
// Do something with $associatedSubjects
}
Se non ci sono argomenti associati, il risultato sarà vuoto.
Se volessimo sapere tutti gli studenti associati a una materia avremmo:
public function getstudents(int $id_subject)
{
$subject= Subject::find($id_subject);
$associatedStudents = $subject->students;
// Do something with $associatedStudents
}
Sincronizzare associazioni (Cancellare o Aggiungere)
Eloquent
mette a disposizione il metodo di sincronizzazione per costruire associazioni molti a molti. Il metodo di sincronizzazione accetta una matrice di identificatori da inserire nella tabella intermedia. Tutti gli ID che non si trovano nell’array specificato verranno rimossi dalla tabella intermedia. Quindi, una volta completata questa operazione, nella tabella intermedia esisteranno solo gli ID nell’array specificato:
// the student $student have 1,2,3,4,5 subjects
$student->subjects()->sync([1, 2, 3, 4, 5]);
Possiamo passare anche ulteriori valori di tabella intermedi, ognuno associato a uno specifico ID, o anche associati a tutti gli ID in array:
// subject 1 has expires value true
$student->subjects()->sync([1 => ['expires' => true], 2, 3]);
// all subjects have active value true
$student->subjects()->syncWithPivotValues([1, 2, 3], ['active' => true]);
Per sincronizzare senza disassociare, puoi utilizzare il metodo syncWithoutDetaching che ci consente di lasciare inalterate le associazioni non specificate:
$student->subjects()->syncWithoutDetaching([1, 2, 3]);
Una forma ci cancellazione è anche quella che prevede di attivare/disattivare una associazione, infatti eloquent
fornisce anche un metodo che “attiva/disattiva” lo stato di collegamento degli ID. Se l’ID specificato è attualmente collegato, verrà scollegato. Allo stesso modo, se è attualmente scollegato, verrà collegato:
$student->subjects()->toggle([1, 2, 3]);
Aggiornare associazioni
Per aggiornare una riga esistente nella tabella intermedia della relazione, possiamo utilizzare il metodo updateExistingPivot
. Questo metodo accetta la chiave esterna del record intermedio e una serie di attributi da aggiornare:
// the student $student have 1,2,3,4,5 subjects
$student= Student::find(1);
$student->subjects()->updateExistingPivot($subjectId, [
'active' => false,
]);
Letture Correlate
Ercole Palmeri