načítání závislých hodnot na základě hodnot z jiné tabulky (MVP)
- tivvit
- Člen | 36
Ahoj,
příklad: načtu si seznam uživatelů z databáze (users->getUsers()) a v templatu je vypíšu. Ke každému uživateli chci ale natáhnout ještě nějaká další data z jiné tabulky, takže si v presenteru zavolám třeba adress->getUserAdress() pro každého uživatele a uložím do pole.
foreach($users as $user) {
$userAdress[$user->id] = $this->adress->getUserAdress($user->id);
}
pak znovu musím zavolat getUsers() (zbytečný dotaz do db) a výsledek předat šabloně a tam to „složitě“ propojovat.
Z toho čuchám prasárnu a že na to jdu blbě.
Čekal bych že v metodě getUsers zavolám i adress->getUserAdress, ale
modely nejde propojovat. Mohl bych tam sice zavolat oba dotazy přímo, ale pak
mám dva stejné dotazy na dvou místech kódu a to určitě nebude dobře.
Jako další řešení mi napadá v presenteru udělat něco jako
users->setUserAdress(adress->getUserAdress) a v modelu uchovávat
všechny uživatele. Pak nastane ale problém v tom zda už jsem uživatele
načetl nebo ne a mít většinu metod jako sigletony taky na 100%
nebude dobře.
Je mi jasný, že tohle by šlo jedním sql dotazem, je to blbej příklad ale spíš mi jde o tom, že mi chybí nějaká základní znalost z MVP a bez ní se dál nepohnu.
Díky
- cesilek
- Člen | 3
K propojení tabulek použiješ metodu related.
Konkrétní použití na velmi podobném případu, jako zde uvádíš nalezneš
v dokumentaci: https://doc.nette.org/cs/database#…
- nanuqcz
- Člen | 822
Ahoj, možná se snažíš vytvořit takovýhle dotaz:
$db->table('user')
->select('user.*')
->select('user.address.city AS address_city, user.address.street AS address_street, ...')
->where('...');
A v šabloně pak normálně
{foreach $users as $user}
<b>{$user->name} {$user->surname}</b>
{$user->address_city} <br>
{$user->address_street} ...
{/foreach}
Předpokládám takovouto strukturu databáze:
- tivvit
- Člen | 36
za ty dva selecty díky doteď jsem to psal přes query() a join.
Problém je v tom, že těch adres může být víc (0:n) takže by se na to
hodilo spíš to related, ale pak na výsledku z toho related potřebuju
provést ještě jeden dotaz.
Popíšu přesně čeho chci docílit (to s tou adresou byl nepovedený
příklad): Mám jednotlivé jednotky (budovy), a každé přiřazuji
pracoviště. Pracoviště jsou vybírány z tabulky a názvy pracovišť jsou
uloženy externě
unit(ID_unit, …), workplace(ID_workplace, ID_name, …),
unit_workplace(ID_unit, ID_workplace), translation(ID_name, cs, en, …)
a chci vytáhnout všechny jednotky a k nim všechny přeložené názvy pracovišť (a nechci aby se provedlo tolik dotazů kolik je pracovišť – chci to předat jako pole a vrátit pole překladů – na to mám funkci).
Vím, že je v Nette překladač a používám ho, ale věci co tahám z databáze jsem chtěl přeložit ještě v ní – asi špatný přístup :(
PS: ten diagram je dělaný ve Visiu?
- tivvit
- Člen | 36
takže chci udělat asi něco takového
public function getUnit()
{
$units = $this->connection->table('unit');
forech($units as $unit)
{
$unit->workplaces = $unit->related('unit_workplace')->related('workplace')->fetchPairs('ID_workplace','ID_name');
}
return $units //kde chci mít i $unit->workplaces
}
a v presenteru si to projdu a přeložím si ty workplaces.
Ale dvě related nejdou a mě by stačilo i nad výsledkem related udělat
jen další select, ale nevím jak to udělat.
A to $unit->workplaces nepůjde, protože workplaces není proměnná té
aktuální activeRow, ta ale nemá žádnou metodu add(), ale implementuje
ArrayAcess takže by to tam mohlo jít dát takto $unit[workplaces], nebo to
chápu špatně?
- nanuqcz
- Člen | 822
Aha, tohle pokud vím v Nette\Database zatím jednoduše nejde. Takže budeš muset použít onu cestu „složitého propojování“.
Zatím se v Nette připravuje (nebo už to Hrach udělal a jen se čeká na mergnutí?) vícenásobný related, který pak bude fungovat takto:
$units = $this->connection->table('unit');
forech($units as $unit)
{
$workplaces = $unit->related('unit_workplace:workplace'); // toto zatím nejde
foreach ($workplaces as $workplace) {
$workplace->capacity;
$workplace->translation->en; // díky ->translation-> se vytvoří automaticky join (to funguje už teď)
}
}
Ten diagram je dělaný v WWW SQL Designeru.
Editoval nanuqcz (14. 4. 2013 12:59)