Tabulka
Cesty relací a tečková notace
Názvy sloupců podporují hlubokou tečkovou notaci pro relace, agregáty, pivoty a morphy. Core parser Relation AST automaticky určuje JOINy, eager loady a podotázky.
Na této stránce
Názvy sloupců podporují hlubokou tečkovou notaci pro relace, agregáty, pivoty a morphy. Core parser Relation AST automaticky určuje JOINy, eager loady a podotázky.
Jednoduchá relace
TextColumn::make('author.name') // belongsTo nebo hasOneTextColumn::make('category.title')
Vnořené relace
TextColumn::make('author.country.name') // 3 úrovně hlubokoTextColumn::make('order.customer.company.name') // 4 úrovně hluboko
Agregáty
TextColumn::make('orders.count') // withCountTextColumn::make('items.sum.amount') // withSumTextColumn::make('ratings.avg.score') // withAvgTextColumn::make('bids.min.amount') // withMinTextColumn::make('bids.max.amount') // withMax
Pivot data
TextColumn::make('tags.pivot.sort_order')TextColumn::make('roles.pivot.assigned_at')->dateTime()
Morph relace
TextColumn::make('commentable.title') // polymorfní
Řazení a filtrování podle singulární relace
Singulární relace — belongsTo, hasOne nebo hasOneThrough — se řeší LEFT JOINem, takže řazení i filtrování proběhne v SQL proti přijoinované tabulce: žádná
whereHas podotázka, žádné filtrování v paměti. Vnořené singulární řetězce se
joinují segment po segmentu (company.country.name → dva zřetězené joiny) a
hasOneThrough se sám rozpadne na dva joiny (base → mezitabulka → cíl).
// Řazení: označ relační sloupec jako sortable.TextColumn::make('company.name')->sortable(); // Filtrování: SelectFilter podporuje tečkovou cestu přímo ve jméně.SelectFilter::make('company.name') ->options(['Acme' => 'Acme', 'Globex' => 'Globex']); // Ekvivalent, pokud chceš mít klíč stavu filtru plochý ('company') a přitom// cílit na relační sloupec:SelectFilter::make('company') ->column('company.name') ->options(['Acme' => 'Acme', 'Globex' => 'Globex']);
Obojí se přeloží na stejný join:
select "users".*from "users"left join "companies" as "users_company" on "users"."company_id" = "users_company"."id"where "users_company"."name" = ? -- filtrorder by "users_company"."name" asc -- řazení
Takto se joinují jen singulární relace (belongsTo, hasOne, hasOneThrough).
To-many relace — hasMany, belongsToMany, hasManyThrough, morphMany — a morph
cíle se pro zobrazení eager-loadují a přes join se řadit ani filtrovat nedají
(join by násobil řádky rodiče).
Scopes a constraints relace (vč. soft delete)
Přijoinovaná strana odpovídá tomu, co vrátí Eloquentova relační query. Relace
nesoucí jakýkoli constraint — global scopes modelu (SoftDeletes, tenancy,
published/active flag, cokoli přes addGlobalScope()) nebo constraints
deklarované přímo na metodě relace (belongsTo(...)->where('active', true)) — se
přijoinuje jako scoped subquery:
left join ( select * from "companies" where "companies"."deleted_at" is null -- SoftDeletes global scope and "companies"."active" = ? -- ->where(...) na relaci) as "users_company" on "users"."company_id" = "users_company"."id"
LEFT JOIN zůstává LEFT JOINem: rodič, jehož related řádek je scopem odfiltrován,
se pořád zobrazí — related hodnota se bere jako prázdná (řadí/filtruje se jako
NULL). U hasOneThrough se scopuje mezitabulka i cílový model. Relace bez scopes
a constraints si drží prostý přímý join na tabulku.
Meze: constraints na metodě relace platí pro
belongsTo/hasOne, ale ne prohasOneThrough(tam se aplikují jen global scopes jeho modelů). Constraint musí být samostatný — korelovaný na rodičovský řádek (whereColumn('companies.x', 'users.y')) se jako subquery vyjádřit nedá.morphOnese přes join nescopuje (eager-loaduje se pro zobrazení).
Jak to funguje
RelationPath::parse('author.country.name')vyprodukuje[RelationSegment('author'), RelationSegment('country'), ColumnSegment('name')]QueryPlannerpostavíRelationGraphurčující optimální strategii přístupu- Singulární
belongsTo/hasOne/hasOneThroughrelace → LEFT JOIN (umožňuje řazení i filtrování;hasOneThroughpřes dva joiny s mezitabulkou) - HasMany/belongsToMany/hasManyThrough/morphMany → eager load (jen zobrazení)
- Agregáty →
withCount()/withSum()podotázky - Pivot → JOIN mezitabulky