Vazby v Eloquentu: Many to Many / Has Many Through

Pokračujeme dalším dílem o vazbách v Eloquentu a tentokrát se detailněji podíváme na vazbu n:n a také si vysvětlíme vztah hasManyThrough, který může být v určitých případech velmi užitečný. Opět si vše ukážeme na praktických příkladech.

Budeme pokračovat ve stejné struktuře jako v minulém díle, tedy prvně si vytvoříme migrace, poté modely a popíšeme si, jak data vytahovat a ukládat, abychom zachovali vazbu n:n.

Na rozdíl od jiných vazeb je u této potřeba vytvořit ještě třetí, propojovací tabulku, tzv. pivot. Tato tabulka nejčastěji slouží jako prostředník a kromě cizích klíčů další sloupce nepotřebuje. V našem případě jsem ještě přidal primární klíč id kvůli jednoznačné identifikaci vazby, nicméně jako klíč bychom mohli i použít kombinaci cizích klíčů, která by vždy měla být unikátní. Dalším sloupcem v pivotu by pak mohl být například datum vytvoření vazby. Propojovací tabulka je v této vazbě velmi důležitá, protože obsahuje různé kombinace cizích klíčů mezi autory a knihami.

Pro definování vazby many to many je potřeba použít v obou modelech metodu belongsToMany().  Pokud by jste chtěli vazby hned vyzkoušet, zjistili by jste, že vše je již nastavené. Jak jste si už určitě všimli, nikde jsem nedefinoval naši pivot tabulku a přesto vše funguje. To je proto, že Eloquent určí název propojovací tabulky na základě jmen modelů a to navíc v abecedním pořadí. To znamená, že Eloquent předpokládá, že propojovací tabulka se bude jmenovat autor_book. Pokud by jste chtěli tabulku pojmenovat jinak, např. jako books_authors_pivot, pak je potřeba tento název definovat jako druhý parametr:

Dále můžete upravit názvy sloupců, které se v pivotu využívají jako cizí klíče. Třetí argument je cizí klíč modelu, ve kterém definujeme vazbu, zatímco čtvrtý parametr je název cizího klíče modelu, ke kterému se připojujeme:

Pokud bychom potřebovali získat informaci z pivot tabulky, pak stačí jít skrze pivot atribut:

Eloquent defaultně předpokládá, že v propojovací tabulce jsou pouze sloupce s cizími klíči. Pokud pivot tabulka obsahuje další sloupce, je potřeba definovat je již v relaci:

Uživatel má informaci o tom, z jaké je země. Článek má informaci o tom, kdo je jeho autor. Nicméně článek už nemá žádnou informaci, z které země je jeho autor, respektive uživatel.

Protože tabulka postsneobsahuje sloupec country_id, vazba hasManyThrough poskytuje přístup k příspěvkům z dané země pomocí $country->posts. Eloquent tento dotaz vykoná tak, že se prvně zkontroluje sloupec $country->postsv propojovací tabulce users. Jakmile získá tyto záznamy, tak podle id uživatelů se najdou záznamy v tabulce posts. První argument v metodě  hasManyThrought je tedy název konečné tabulky, ke které se chceme dostat, a druhý argument je název propojovací tabulky.

Není vám něco jasné, mám někde chybu nebo chcete přidat svůj názor na článek? Napište do komentářů pod článkem.