ActiveRow, relace many-to-many – vypsání propojeného názvu bez iterací nad výsledky

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Milan Obrtlík
Člen | 50
+
0
-

Dobrý den, mám tři DB tabulky (tři tečky znamenají, že tam jsou ještě nějaké snad nepodstatné sloupce):
groups: group_id, name, ...
users: user_id, active_group_id, ...
users_groups: group_id, user_id

Zjednodušeně: uživatelé jsou rozděleni do skupin (many to many), active_group indikuje právě zvolenou skupinu.

Když chci vypsat všechny skupiny pro daného uživatele, vyberu je z databáze tímto dotazem:

$this->database->table('users_groups')->where('user_id', $user_id)->fetchAll();

a v Latte to vykreslím takto

<li n:foreach="$users_groups as $user_group">{$user_group->group->name}</li>

Nette si s tím poradí naprosto fenomenálně přesně jak je psáno v dokumentaci.

A teď věc, se kterou potřebuji poradit – jde vypsat právě zvolená skupina mimo foreach?

Přišel jsem jenom na toto

<span>{$users_groups[$user->selected_group_id]->group->name}</span>

Ale to vyžaduje mít nastavený primární klíč na tabulce users_groups.group_id a pak už nebude možné mít více uživatelů ve skupině.

Mysteria
Člen | 797
+
0
-

Zkusil bych něco jako:

$user = $this->database->table('users')->wherePrimary(1);
echo $user->ref('groups', 'active_group_id')->name; // Aktivní skupina, možná půjde zkrátit na $user->active_group->name
foreach ($user->related('users_groups', 'user_id') as $userGroup) {
	echo $userGroup->group->name; // Všechny skupiny
}
filsedla
Člen | 101
+
0
-

Podle mě

<span>{$users_groups[$user->selected_group_id]->group->name}</span>

dá stejný výsledek jako

<span>{$user->selected_group->name}</span>

bez potřeby primárního klíče na group_id

Milan Obrtlík
Člen | 50
+
0
-

Pánové, moc se omlouvám, zadal jsem to nepřesně. $user je objekt třídy Nette\Security\User a ve skutečnosti id zvolené skupiny beru pomocí $user->getIdentity()->selected_group_id. Není tedy možné využít vychytávek Nette\Database.

I kdyby $user byl objekt třídy Nette\Database, tak by to stejně prásklo další dva dotazy na DB, sice jsou to rychlé dotazy a prakticky ničemu nevadí – ale když si to člověk řekne několikrát než dosáhne funkčnosti daného bloku a celá aplikace se skládá z několika takových bloků, hned máme nezanedbatelnou hromadu úplně zbytečných dotazů.