vícenásobný related – problém

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

Narazil jsem na chybu(možná na mé straně) při použití funkce related().
Při vykonání kódu

{foreach $galleries as $gallery}
	<div id="tabs-{$gallery->id}">
	    <ul id="sortable1" class="connectedSortable gallerySortable ui-helper-reset">
	    {foreach $gallery->related('image') as $image}
		{var $lang = $image->related('image_lang_data', 'image_id')->where("language_id = ?", 1)->fetch()}
		    <li id="{$image->id}" class="ui-state-default">
			<img src="{$basePath}/images/small/{$image->id}.jpg" alt="{$lang->title}">
		    </li>
		{/foreach}
	    </ul>
	</div>
    {/foreach}

Nette Database provede dotazy

SELECT `id`
FROM `gallery`

SELECT *
FROM `gallery_lang`
WHERE (`gallery_lang`.`gallery_id` IN (1, 2))
SELECT *

SELECT *
FROM `image`
WHERE (`image`.`gallery_id` IN (1, 2))

FROM `image_lang_data`
WHERE (`image_lang_data`.`image_id` IN (1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25)) AND (`language_id` = 1)

SELECT *
FROM `image_lang_data`
WHERE (`image_lang_data`.`image_id` IN (NULL)) AND (`language_id` = ?)

Což skončí samozřejmě chybou.
Zde je schéma databáze
https://www.dropbox.com/…b_schema.png
a zde dump, pro jistotu i s daty
https://www.dropbox.com/…/db_dump.sql

Editoval ajda2 (30. 7. 2012 18:34)

ajda2
Člen | 66
+
0
-

Jako možné „řešení“ mě napadlo šabloně předat celý model, místo již vykonaného selectu a volat select v každém průchodu foreache. O něco takového sem se dřív pokoušel, ale Nette Database jen vložilo všechny selecty do sebe a spojilo podmínku. Takže stejně nepoužitelné.

vvoody
Člen | 910
+
0
-

Aky presne error ti to hadze? Skusil som si to a u mna je notiska: Trying to get property of non-object v sablone na {$lang->title}. To je celkom jasne, len sa nenasiel zaznam v db, preto fetch vratilo NULL namiesto ActiveRow. Ale divnejsie je preco nette u teba nevykona ziadny dotaz nad gallery. Predsa v premennej $galleries mas vyber z tabulky gallery?

ajda2
Člen | 66
+
0
-

@vvoody: První dotaz jsem neuváděl, nepřišel mi důležitý – doplnil jsem.
Hodí mi to naprosto stejnou hlášku jako Tobě. Problém je ale v tom, že ten obrázek v DB je.
Nette ho jej dokonce načte

FROM `image_lang_data`
WHERE (`image_lang_data`.`image_id` IN (1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25)) AND (`language_id` = 1)

Jenomže ho načte špatně(brzy) – je to ten s ID 25. Má gallery_id = 2
a poté v druhém cyklu, kdy se prochází galerie, by se mělo vzít z DB image kde je gallery_id = 2, ale provede se toto

SELECT *
FROM `image_lang_data`
WHERE (`image_lang_data`.`image_id` IN (NULL)) AND (`language_id` = ?)

A v tom je podle mě ten problém. Místo NULL by tam mělo být 25. Řešilo se to zde https://forum.nette.org/…ette-2-1-dev
ale byl sem požádán o vytvoření nového vlákna

vvoody
Člen | 910
+
0
-

Aha tamto, tak to je dost neprijemny bug :) vsimol som si ze related ma treti parameter $forceNewInstance, ktory mozno nastavit na TRUE, cim sa to viacnasobne zanorenie „zredukuje“ ale zase sa znasobi pocet dotazov na db co urcite nechceme.

{foreach $gallery->related('image',null,true) as $image}

A co takto do sablony si poslat vyber obrazkov zoradenych podla gallery id

$gals = $this->context->database->table('gallery');
$imgs = $this->context->database->table('image')->where('gallery_id',$gals->select('id'))->order('gallery_id');
$this->template->imgs = $imgs;

a v sablone to uz treba len nejako rozumne odsledovat kedy sa pri prechadzani obrazkami zmeni galeria, toto je trosku humus :D

{? $gal = 0}
{foreach $imgs as $img}
	{if $img['gallery_id'] != $gal}
		{if $gal != 0}
		</ul>
	</div>
		{/if}
	<div>
		<ul id="sortable1" class="connectedSortable gallerySortable ui-helper-reset">
		{$img['gallery_id']}
		{? $gal = $img['gallery_id']}
	{/if}

			{var $lang = $img->related('image_lang_data', 'image_id')->where("language_id = ?", 1)->fetch()}
			<li id="{$img->id}" class="ui-state-default">
				<img src="{$basePath}/images/small/{$img->id}.jpg" alt="{$lang->title}">
			</li>

	{last}
		</ul>
	</div>
	{/last}
{/foreach}

ale panel mi nakoniec ukazuje len 3 query :) nad kazdou tabulkou jednu. Samozrejme len ako docasne riesenie, ta sablona vyzera otrasne.

hrach
Člen | 1838
+
0
-
  • forceNewInstance je blbost ;) To uz tu v novych vetvych neni a nebude. Bylo to jen docasne, pokus o fix jineho bugu, rozbilo to jine veci.
  • mne cely tvuj priklad naprosto funguje. Prosim jeste jednou se ujisti, ze pouzivas f-database-refactoring a promazes veskerou cache.
vvoody
Člen | 910
+
0
-

Potvrdzujem, povodny priklad na f-database-refactoring ide aj mne.
PS: cache premazana :)

ajda2
Člen | 66
+
0
-

@hrach, @vvoody:
Právě jsem pro jistotu vyzkoušel stáhnout Nette 2.0.4 a poté jsem zkusil https://github.com/…-refactoring a se stejným výsledkem.
Pomohlo jen přidat forceNewInstance.
Cache samozřejmě pokaždé mažu.
Nemůže být problém ještě někde jinde? Nastavení DB, PHP, Nette?
Poskytnu klidně zdrojáky, či cokoliv co bude potřeba. Chtěl bych to vyřešit.
Tady je laděnka s chybou. https://www.dropbox.com/…base_bug.htm Je tam dumplá proměnná $lang. V posledním řádku, kde by měl být ActiveRow z tabulky „image_lang_data“ s „image_id“ = 25 je FALSE. Což bude podle mě způsobeno posledním dotazem do DB

SELECT *
FROM `image_lang_data`
WHERE (`image_lang_data`.`image_id` IN (NULL)) AND (`language_id` = ?)

Editoval ajda2 (1. 8. 2012 9:30)

Eda
Backer | 220
+
0
-

Vypadá to, že s ajdou2 máme úplně stejný problém. Fakt mne zajímá, jak to dopadne :-)

hrach
Člen | 1838
+
0
-

Tak jeste jednou, $forceNewInstance nema vyznam, protoze uz nikdy nebude, pac se to delat ted vzdy :P Hosi, fakt nevim co s tim, prosim, spuste si doma ty testy: https://forum.nette.org/…ette-2-1-dev#…
a rekneme te mi, jestli vsechny projdou.

Editoval hrach (2. 8. 2012 20:32)

ajda2
Člen | 66
+
0
-

@hrach: Tak jsem spustil testy. Přikládám jejich výsledek https://www.dropbox.com/…exm/test.log
S testy nemám žádnou zkušenost, takže pokud je chyba ještě na mé straně, prosím dejte mi vědět.

Chápu, že $forceNewInstance je slepá ulička, ale zatím pro mne jediné funkční řešení.
Každopádně je dost divné, že někomu to funguje a někomu ne. Jiné nastavení Mysql, PHP?

hrach
Člen | 1838
+
0
-

Hm, urcite si je nespustil tak jak sem chtel. Nutno spustit toto „RunTests.bat -j 1 Nette\Database“

ajda2
Člen | 66
+
0
-

Omlouvám se, nevšiml sem si, že jsi to psal i v minulém vlákně.
Provedl jsem testy tak jak si chtěl a všech 23 testů proběhlo v pořádku.
Napadá tedy někoho, kde ještě může být chyba?

ajda2
Člen | 66
+
0
-

Nedalo mi to a vyzkoušel sem založit kompletně nový projekt. Použil jsem f-db-dev od Hracha. Vytvořil sem novou databázi a naplnil ji dumpem, co tady přikládám. Použil sem ho schválně, protože někdo psal, že mu to funguje. Jenže stejně to nefunguje. Jsem už opravdu bezradný.
Přikládám PHP info, jestli třeba není zakopaný pes tam. https://www.dropbox.com/…fo%28%29.htm

hrach
Člen | 1838
+
0
-

Prosim te, muzes mi cely projekt zabalit vcetne dumpu? Ze bych zkusil. Jinak v phoinfo nevidim nic, respektive ani nevim co mam hledat. Az na to, ze je to starsi verze php.

ajda2
Člen | 66
+
0
-

@hrach: Poslal sem ti projekt na mail, který máš uvedený na svém webu.
PHP info taky nevím, ale nic jiného než problém na straně PHP, nebo MySQL mě už nenapadá.
Případně provedu update PHP, pokud to bude potřeba.

ajda2
Člen | 66
+
0
-

Tak konečně se problém VYŘEŠIL!
Problém byl tam, kde bych ho vůbec nečekal. Při stažení f-database-refactoring Nette od hracha jsem dal možnost stáhnout v zipu přímo z Gitu. Z nějakého důvodu to nestáhlo poslední commit. Problém vyřešila synchronizace repository. Takže v f-database-refactoring to opravdu funguje, jen je si třeba ohlídat staženou verzi. Poté stačí přehodit pořadí parametrů v konstruktorech a v továrničkách, aby to korespondovalo s „ofic.“ Nette.

@hrach: Co tě přimnělo k prohození parametrů v konstruktorech tříd Selection, GroupedSelection a ActiveRow? Jinak moc děkuji za ochotu!

hrach
Člen | 1838
+
0
-

Navrhova cistota, kdy v grouped selection to bylo divne (tableName, connection, key, active) :) Vzhledem k tomu, ze sem nevedel, ze nekdo spatne napsal do manualu, ze se to ma dedit, tak sem ani netusil, ze jde o BC. Btw, quickstart by v tomto smeru uz mel byt opraven.

Eda
Backer | 220
+
0
-

Taky jsem f-database-refactoring stahoval přes odkaz na ZIP archiv… To bude ono.