načítání závislých hodnot na základě hodnot z jiné tabulky (MVP)

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

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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)

tivvit
Člen | 36
+
0
-

díky za odpověď. Zatím to udělám tak aby to fungovalo i když to nebude hezké a až to půjde lépe, tak tak to opravím.

Jinak ten nástroj na diagramy je super, něco takového jsem hledal.

A poslední dotaz, kdybych používal doctrine tak by tohle šlo lépe?