Dotaz na databázy v latte

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

Poradí prosím někdo jak lze v latte šabloně položit dotaz na konkrétní sloupec v tabulce podle id?

Mám to asi takhle, ale to nefunguje:

{foreach $database->table('vzkazy')->order('datum DESC') as $vzkaz}

      <table class="tabulka">
      <tr><td class="malePismo"></td><td class="vzkaz">{$vzkaz->predmet}<td></tr>
      <tr><td class="malePismo">{$database->table('uzivatele')->where('id',$vzkaz->uziv_id)->select('nick')}<br/>
      {$vzkaz->datum |date:'%d.%m.%Y'}</td><td class="vzkaz">{$vzkaz->vzkaz}<td></tr>
      <tr> <td n:if="$user->isAllowed([vzkaz, $user->id, $vzkaz], edit)" class="vzkaz"><a n:href="edit $vzkaz->id">EDIT</a></td><td n:if="$user->isAllowed([vzkaz, $user->id, $vzkaz], edit)" class="vzkaz"><a n:href="Homepage:smaz $vzkaz->id">SMAZ</a></td></tr>
      </table>
     {/foreach}


       </br>

Jde mně o tento dotaz Vzkazy to normálně vypíše..

$database->table('uzivatele')->where('id',$vzkaz->uziv_id)->select('nick')

id int(11) Auto Increment
nick varchar(50)
email varchar(50)
poznamka varchar(200) NULL
registrace datetime NULL
naposledyOnline datetime NULL
heslo varchar(100)

ViPEr*CZ*
Člen | 817
+
0
-

Doporučuji nastudovat quickstart a modely a pak v dokumentaci juknout i na použití NDB. Každopádně takto ošklivě to samozřejmě musí fungovat taky, ale toto:

{$database->table('uzivatele')->where('id',$vzkaz->uziv_id)->select('nick')}

vrací objekt, takže to ten nick nevypíše… takhle už by ho to vypsat mělo:

{$database->table('uzivatele')->get($vzkaz->uziv_id)->nick}
Miky0007
Člen | 73
+
0
-

ok díky a co je na tom prosím ošklivýho?

ViPEr*CZ*
Člen | 817
+
0
-

Miky0007 napsal(a):

ok díky a co je na tom prosím ošklivýho?

To poznáš až se mrkneš na ten quickstart… v šabloně (view vrstvě) by jsi neměl takhle pracovat s databází. A taky předpokládám, že tabulka vzkazy je propojená s tabulkou uzivatele přes sloupec uziv_id, tak že to použití $database->table(‚uzivatele‘)->get($vzkaz->uziv_id)->nick je zbytečně složité a dalo by se využít toho spojení $vzkaz->uzivatele->nick což je podstatně jednodušší zápis.

Miky0007
Člen | 73
+
0
-

Ano máš pravdu tabulka je propojená přes uziv_id…Proběhnu teda quick start…

Miky0007
Člen | 73
+
0
-

Máš pravdu už nepředávám view spojení na databázi, ale jen tabulku, kterou vytáhnu v modelu…
Model:

function getVzkaz()
	{
		return $this->database->table('vzkazy');

	}

Presenter:

$this->template->vzkazy = $this->context
			->vzkazModel->vzkaz->page($page, 5);

View:

{default $page => 1}
     {foreach $vzkazy->order('datum DESC') as $vzkaz}

        <table class="tabulka">
        <tr><td class="malePismo"></td><td class="vzkaz">{$vzkaz->predmet}<td></tr>
        <tr><td class="malePismo">{$vzkaz->uzivatele->nick}<br/>
        {$vzkaz->datum |date:'%d.%m.%Y'}</td><td class="vzkaz">{$vzkaz->vzkaz}<td></tr>
        <tr> <td n:if="$user->isAllowed([vzkaz, $user->id, $vzkaz], edit)" class="vzkaz"><a n:href="edit $vzkaz->id">EDIT</a></td><td n:if="$user->isAllowed([vzkaz, $user->id, $vzkaz], edit)" class="vzkaz"><a n:href="Homepage:smaz $vzkaz->id">SMAZ</a></td></tr>
        </table>
       {/foreach}

Akorát mně to zatím píše, že nebyla nalezena reference…

ViPEr*CZ*
Člen | 817
+
0
-

To už bude asi chyba někde jinde… v databázi, jestli máš správně nastavený ten cizý klíč.

Miky0007
Člen | 73
+
0
-

Tabulka vzkazy
Sloupec Typ Komentář
id int(11) Auto Increment
vzkaz varchar(400)
datum datetime
predmet varchar(80)
uziv_id int(11)
Indexy
PRIMARY id
INDEX uziv_id
Pozměnit indexy
Cizí klíče
Zdroj Cíl Při smazání Při změně
uziv_id uzivatele(id) NO ACTION NO ACTION Změnit
Přidat cizí klíč
Triggery
Přidat trigger

Tabulka uzivatele

Sloupec Typ Komentář
id int(11) Auto Increment
nick varchar(50)
email varchar(50)
poznamka varchar(200) NULL
registrace datetime NULL
naposledyOnline datetime NULL
heslo varchar(100)
Indexy
PRIMARY id
Pozměnit indexy
Cizí klíče
Přidat cizí klíč
Triggery
Přidat trigger

ViPEr*CZ*
Člen | 817
+
0
-

Hmm takhle nevím. Předpokládám, že tu chybějící referenci to vyhazuje na tomto: {$vzkaz->uzivatele->nick}
Zkusil bych ještě smazat cache. Taky bych to zkusil takto: {dump $vzkaz->ref(‚uzivatele‘, ‚uziv_id‘)} co to vůbec vypíše do debugBaru.

Miky0007
Člen | 73
+
0
-

Ano přesně jak říkáš..Cache jsem smazal a dělá to furt to samí a po dumpu to vypsalo asi toto:
$vzkaz->ref(‚uzivatele‘, ‚uziv_id‘)
Nette\Database\Table\ActiveRow(3) ▼ {
table private ⇒ Nette\Database\Table\Selection(16) ▼ {
connection protected ⇒ Nette\Database\Connection(6) ▼ {
dsn private ⇒ „mysql:host=localhost;dbname=satec“ (33)
driver private ⇒ Nette\Database\Drivers\MySqlDriver(1) { … }
preprocessor private ⇒ Nette\Database\SqlPreprocessor(6) { … }
databaseReflection private ⇒ Nette\Database\Reflection\DiscoveredReflection(4) { … }
cache private ⇒ Nette\Caching\Cache(4) { … }
onQuery ⇒ array(1) [ … ]
}
sqlBuilder protected ⇒ Nette\Database\Table\SqlBuilder(12) ►
name protected ⇒ „uzivatele“ (9)
primary protected ⇒ „id“ (2)
primarySequence protected ⇒ FALSE
rows protected ⇒ array(1) ▼ {
1 ⇒ Nette\Database\Table\ActiveRow(3) { RECURSION }
}
data protected ⇒ array(1) ▼ {
1 ⇒ Nette\Database\Table\ActiveRow(3) { RECURSION }
}
referenced protected ⇒ array(0)
referencing protected ⇒ array(0)
referencingPrototype protected ⇒ array(0)
aggregation protected ⇒ array(0)
accessed protected ⇒ array(1) ▼ {
id ⇒ TRUE
}
prevAccessed protected ⇒ NULL
observeCache protected ⇒ TRUE
checkReferenced protected ⇒ FALSE
keys protected ⇒ array(0)
}
data private ⇒ array(7) ►
modified private ⇒ array(0)
}

Miky0007
Člen | 73
+
0
-

Tabulku uživatele předávám v presenteru do view takto:

$this->template->uzivatele=$this->context->userModel->getUser();

A v modelu to vypadá:

function getUser()
	{
		return $this->database->table('uzivatele');

	}
ViPEr*CZ*
Člen | 817
+
0
-

No dump vypadá dobře, kdyby ti to nefungovalo, tak by se dumpovalo FALSE. Zkus tam ještě dát toto:

$vzkaz->ref(‚uzivatele‘, ‚uziv_id‘)->nick
Miky0007
Člen | 73
+
0
-

Tak to normálně funguje…Díky moc chlape

ViPEr*CZ*
Člen | 817
+
0
-

Miky0007 napsal(a):

Tak to normálně funguje…Díky moc chlape

Ok. V podstatě to dělá to samé jako ten původní zápis {$vzkaz->uzivatele->nick} jen přes tu metodu ref jsi řekl v druhým parametru přes jaký sloupec se má podívat do té tabulky uzivatele.
Proč ti nefunguje ten zkrácený zápis přesně nevím… musel bych asi někde zkoušet, takhle na první pohled to nevidím. Pokud to je verze před 2.0.6, tak tam taky záleželo na konvenci zápisu jména cizýho klíče. Jinak pak Reflexe neví přes jaký sloupec se podívat.

Miky0007
Člen | 73
+
0
-

Každopádně děkuju tohle funguje a snad to není taková čunárna jako předtím :-)

ViPEr*CZ*
Člen | 817
+
0
-

Miky0007 napsal(a):

Každopádně děkuju tohle funguje a snad to není taková čunárna jako předtím :-)

No oddělil jsi to do modelu což je správně, ten zápis přes ref je taky správně (jen je složitější, ale správně). Takže tyto dva body co řeší toto téma jsou určitě pořešený.
Můžeš ještě vykoumat proč nefunguje ten zkrácenej zápis, aby to bylo ještě lepší ;-)

Miky0007
Člen | 73
+
0
-

Jo já to určitě prokoumu…Ale až na to budu mít víc času..ted se chci s tou aplikací posunout víc dopředu…Ale chápu to správně, že když pracuju s více tabulkama musím v presenteru z modelu předat všechny tabulky že? Jak by vypadal prosím dotaz kdybych chtěl vypsat třeba ze třech tabulek všechny uživatele a jejich oprávnění? Pokud by tabulky vypadali třeba takhle:
Tabulka Uzivatele
Id
Jmeno
Email

Tabulka Role
Id
Opravneni

Tabulka Uziv_Opravneni
uzivatel_id – cizí klíč z tabulky uzivatele
uzivatelska_role_id – cizí klíč z tabulky role

Jde to vůbec? Když každej uživatel může mít více oprávnění…

ViPEr*CZ*
Člen | 817
+
0
-

Takhle se to nedělá… stačí na to dvě tabulky propojené vazbou 1:N.

user
userID
name
email

role
roleID
name
userID (cizí klíč na uživatele)

V tuto chvíli může uživatel mít více rolí a tudíž jeden uživatel může mít více řádků v tabulce role. Pak to mohu zjistit takto:

$users = $database->table("user");

Tímto si získáme všechny uživatele. Nebo lépe řečeno objekt Selection, nad kterým lze iterovat. V praxi:

foreach($users as $user) {
  $user->nick;
}

a pokud chci role k danému uživateli mohu použít metodu related:

foreach($users as $user) {
  $user->nick;
  $roles = $users->related("role", "userID");
  foreach ($roles as role) {
     $role->name;
  }
}

A nebo to jde pak obráceně jak už jsem ukazoval (získat si role například podle name a k danému řádku s rolí si mohu přes klíč získat uživatele).

jiri.pudil
Nette Blogger | 1032
+
0
-

Takhle se to nedělá… stačí na to dvě tabulky propojené vazbou 1:N. (…) V tuto chvíli může uživatel mít více rolí a tudíž jeden uživatel může mít více řádků v tabulce role.

V tvém návrhu ale nemůže mít více uživatelů stejnou roli; tedy ne bez duplicit v tabulce „role“. Řekl bych, že je vazba M:N zcela na místě.

Editoval jiri.pudil (27. 12. 2012 17:57)

Miky0007
Člen | 73
+
0
-

Já to možná napsal blbě…Ono jeden uživatel může mít více rolí..Ale jedna role má samozřejmě více uživatelů..Takže mně příjde že tři tabulky jsou na místě…Teda aspoň nás to tak kdysi učili na škole :-) S těmi třema tabulkama to nějak jde? Ted mě tak napadlo, že tabulky propojuju až ve view..Nebylo by možná lepší to udělat už v modelu…nákou funkcí?

ViPEr*CZ*
Člen | 817
+
0
-

jiri.pudil napsal(a):

Takhle se to nedělá… stačí na to dvě tabulky propojené vazbou 1:N. (…) V tuto chvíli může uživatel mít více rolí a tudíž jeden uživatel může mít více řádků v tabulce role.

V tvém návrhu ale nemůže mít více uživatelů stejnou roli; tedy ne bez duplicit v tabulce „role“. Řekl bych, že je vazba M:N zcela na místě.

Máš pravdu, moje chyba… takhle to bude určitě lepší… omlouvám se ;-)
Asi jsem se nechal chytit na této větě: „Jde to vůbec? Když každej uživatel může mít více oprávnění…“ a už jsem ani nepřemýšlel moc dál a udělal jsem ukázku jak pracují vazby. :-D

ViPEr*CZ*
Člen | 817
+
0
-

Miky0007 napsal(a):

Já to možná napsal blbě…Ono jeden uživatel může mít více rolí..Ale jedna role má samozřejmě více uživatelů..Takže mně příjde že tři tabulky jsou na místě…Teda aspoň nás to tak kdysi učili na škole :-) S těmi třema tabulkama to nějak jde? Ted mě tak napadlo, že tabulky propojuju až ve view..Nebylo by možná lepší to udělat už v modelu…nákou funkcí?

Přes ty tři tabulky se to dělá úplně stejně jak jsem už popisoval se dvěma ;-)
V šabloně si šáhnout přes reference na druhou tabulku je ok ;-)

Miky0007
Člen | 73
+
0
-

Tak já to zejtra nějak nazkouším…díky moc za pomoc