Relații unu-la-mulți
Lectură estimată: 3 minute
Estimare pentru text, la un ritm de 180 de cuvinte pe minut. Timpul pentru analizarea codului, exerciții și proiecte se adaugă separat și depinde de ritmul tău.
Relația unu-la-mulți e cea mai frecventă: un autor are multe articole, o categorie are multe produse, o comandă are multe linii. În Laravel o definești pe model cu `hasMany` și `belongsTo`, plus o cheie străină în migrație.
Migrația
Schema::create("articole", function (Blueprint $table) {
$table->id();
$table->foreignId("user_id")->constrained()->cascadeOnDelete();
$table->foreignId("categorie_id")->nullable()->constrained();
$table->string("titlu");
// ...
});
// constrained() deduce tabelul (users, categorii) din numele coloaneiDefinirea pe modele
// User.php
public function articole() { return $this->hasMany(Articol::class); }
// Articol.php
public function autor() { return $this->belongsTo(User::class, "user_id"); }
public function categorie() { return $this->belongsTo(Categorie::class); }Folosirea relației
$user->articole; // colecție de articole
$user->articole()->publicate()->get(); // cu scope-uri și condiții
$articol->autor->name; // navighezi în sens invers
$user->articole()->create([...]); // creezi legat automat de usercascadeOnDelete și nullable
`cascadeOnDelete()` șterge articolele când ștergi autorul. `nullOnDelete()` le lasă dar pune `categorie_id` pe null. `nullable()` pe cheia străină înseamnă „relația e opțională". Alegi în funcție de regulă de business: un articol fără autor n-are sens (cascade), un articol fără categorie da (nullable).
Pagina unei categorii
public function show(Categorie $categorie) { $articole = $categorie->articole() ->publicate() ->latest("publicat_la") ->paginate(10); return view("categorii.show", compact("categorie", "articole")); }
Exercițiu
Adaugă relația categorie–articole. Migrație cu foreignId nullable + constrained. Metode hasMany/belongsTo pe modele. O pagină de categorie care listează articolele ei publicate, paginat.
Greșeli frecvente
- Uiți constrained() și n-ai integritate referențială la nivel de bază.
- Definești doar o parte a relației (hasMany fără belongsTo sau invers).
- Numele metodei nu respectă convenția și trebuie să dai al doilea argument peste tot.
- Nu te gândești ce se întâmplă la ștergere (cascade vs. null vs. restrict).
De reținut
- foreignId(...)->constrained() în migrație pentru cheia străină.
- hasMany pe „unul", belongsTo pe „mulți".
- $parinte->copii și $copil->parinte pentru navigare.
- Alege comportamentul la ștergere conștient.
Pe scurt
Unu-la-mulți: cheie străină + hasMany/belongsTo. Apoi navighezi relația în ambele sensuri, cu scope-uri și condiții.
Relație unu-la-mulți și interogare limitată
Relația definește cum se leagă modelele, iar interogarea decide ce date sunt citite. Pentru cererile utilizatorului curent, pornește din relația lui, nu din toate cererile și filtrare în PHP. Aceasta reduce riscul de acces accidental și volumul transferat. Totuși, relația nu înlocuiește policy pentru toate operațiile. Păstrează paginarea, fiindcă un utilizator poate acumula multe înregistrări.
Exemplu de lucru
În User:
public function serviceRequests(): HasMany { return $this->hasMany(ServiceRequest::class); }
În ServiceRequest:
public function user(): BelongsTo { return $this->belongsTo(User::class); }
Listă:
$requests = $request->user()->serviceRequests()->latest()->paginate(20);Interpretarea rezultatului
Lista conține numai resursele utilizatorului autentificat și maximum pagina cerută. Importă tipurile de relație potrivite. Testează cu doi utilizatori și cereri diferite; un test cu un singur utilizator nu poate detecta o scurgere între conturi.
Exercițiu de consolidare
Adaugă filtrul status=new și verifică faptul că totalul paginării se referă la setul filtrat.
Aplicație practică
Sarcina
Definește relația dintre autor și articole.
Rezolvare orientativă și verificare
Autorul are hasMany, articolul belongsTo. Creează un autor fără articole și verifică rezultatul gol.
Greșeală de evitat
O relație opțională trebuie tratată explicit la afișare.
Documentație și surse
Ți-a plăcut lecția? Continuă cursul complet
Ai citit o lecție gratuită. Celelalte lecții, aplicațiile practice și materialele se deblochează odată cu cursul.
149 lei
Plată unică, acces pe viață la toate cele 6 lecții.
Vezi ce conține cursul →