Laravel – relacje

  laravel

Tworząc relację, bierzemy dwa modele, które są ze sobą powiązane. Jeżeli funkcję z jednego modelu nazwiemy jak nazwę modelu drugiego, to laravel sam je połączy

Relacja 1 do 1

//To w modelu video
public function user() {
    return $this->belongsTo('App\User');
}

Relacja 1 do wielu

//To w modelu user
public function videos() {
 return $this->hasMany('App\Video);
}

Następnie w migracji

$table->integer('user_id')->unsigned(); //unsigned to tylko informacja, że id musi być nieujemny
$table->foreign('user_id)->references('nazwaPolaZInnejTabeli')->on('nazwaTabeli);

Wyświetlanie nazwy użytkownika we wpisie

{{ $post->user->name }}

Relacja wiele do wielu (na przykładzie kategorii)

Tworzymy nową migrację. Nowa tabela będzie łączyć id wpisu z id kategorii.

$table->integer('category_id');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
//onDelete oznajmia, że jeżeli będziemy usuwać jakieś video, to ten rekord też ma zniknąć

kolejnym krokiem są zmiany w modelu. Pierwszy jest model kategorii

class Category extends Modelclass Category extends Model{    
   public function posts() {    
      return $this->belongsToMany('App\Post')->withTimestamps();    
   }
}

i adekwatnie trzeba zrobić dla drugiego modelu. Nazwa funkcji niech będzie w liczbie mnogiej (bo relacja wiele do wielu)

Pivot table

W którymś modelu np w kategorii trzeba dorzucić utworzenie (i dropnięcie w down) tabeli. Jej nazwa to alfabetyczne model1_model2. Jako primary trzeba dorzucić połączenie obu kolumn

Schema::create('images_category_image', function (Blueprint $table) {
 $table->increments('images_category_id');
 $table->integer('image_id');
 $table->primary(['images_category_id', 'image_id']);
});

Zapis do Pivot Table

koniecznie musi odbyć się po zapisie normalnego posta, żeby system wiedział, jakie ID posta przypisać w pivot. Jeżeli zapisujesz tablicę wartości, to name pola wpisz z „[]’, jak tutaj:

select id="add_categories" multiple="multiple" name="add_categories[]"

a funkcja zapisu wygląda tak: (nie ogarnąłem jeszcze, czy da się zrobić to skróconą wersją (image_categories() to nazwa funkcji zwracającej relację)

$image = new Image;
$image->title = request('title');
$image->thumb = request('thumb');
$image->save();
$image = Image::create(request(['title', 'thumb']));

$image->images_catetories()->sync($request->add_categories);
return redirect()->route('newImage')->with('status', 'Obraz został zapisany');

        //Second solution for save multiple - optimized to one DB request, but can't figure out, how to attach pivot data
        //image = new Image;
        //$inputs = Input::get('row');
        //$image::insert($inputs); //perfect, only one query

Pobieranie modelu (bądź kolekcji modeli) z warunkiem pivota

(w tym przypadku images_categories to relacja)

$posts = Image::whereHas('images_categories', function ($query) use ($categoriesIdArray) {            
   $query->whereIn('id', $categoriesIdArray);
})->latest()->get();

Pobieranie modelu (bądź kolekcji modeli) z warunkiem pivota

(w tym przypadku images_categories to relacja). $categoriesIdArray nie jest konieczne. W ten sposób po prostu przekazuje się do funkcji zmienne.

$posts = Image::whereHas('images_categories', function ($query) use ($categoriesIdArray) {            
   $query->whereIn('id', $categoriesIdArray);
})->latest()->get();