Migrace na Nette 2.1 – getReferencedTable
- kolsi
- Člen | 131
Ahoj,
postupně se snažím migrovat ze staré verze Nette 2.0.17 na 2.1.8 a narazil
jsem na problém, který nevím, jak jednoduše vyřešit.
Missing argument 3 for Nette\Database\Table\Selection::getReferencedTable(), called in XXX on line 53 and defined
Když kouknu do staré verze, tak getReferencedTable měla jako 3. parametr „$checkReferenced = FALSE“, ale nová verze tam má „$checkPrimaryKey“ (čili nyní je hodnota povinná), ale vypadá to, že nebude stačit jenom všude nastavit na FALSE.
Největší problém vidím v tom, že ať čtu jak chci, tak nikde o tom nevidím ani zmínku: https://doc.nette.org/…tions/to-2-1
Takže co s tím?
- kolsi
- Člen | 131
Tak důvodů je víc, ale ten hlavní je, že to chceme upgradovat postupně (těch věcí, co se rozbilo je víc než bych čekal).
Problém jsem vyřešil zatím tak, že jako třetí parametr getReferencedTable() jsem dal všude „id“ – nevím, jestli jsem pochopil správně, že tam má být název sloupce odkazované tabulky, ale vypadá to, že to funguje.
Zatím se ale nemůžu zbavit pocitu, že Nette 2.1 je prostě pomalejší než předchozí verze a každá stránka generuje i o pár desítek více DB dotazů, např.
$not_added_roles = $this->model->getRoles()->fetchPairs('name', 'parent');
vygeneruje v Nette 2.0.17 jeden dotaz:
SELECT *
FROM `pd2_acl_role`
WHERE (`id` IN (1, 3, 4))
.../app/modules/CoreModule/model/Security/Authorizator.php
ale v Nette 2.1.8 vygeneruje 3 úplně stejné dotazy:
SELECT `id`, `name`
FROM `pd2_acl_role`
WHERE (`id` IN (1, 3, 4))
.../app/modules/CoreModule/model/Security/Authorizator.php:32
SELECT `id`, `name`
FROM `pd2_acl_role`
WHERE (`id` IN (1, 3, 4))
.../app/modules/CoreModule/model/Security/Authorizator.php:32
SELECT `id`, `name`
FROM `pd2_acl_role`
WHERE (`id` IN (1, 3, 4))
.../app/modules/CoreModule/model/Security/Authorizator.php:32
Editoval kolsi (27. 11. 2014 10:22)
- kolsi
- Člen | 131
Tak s tím fetchPairs jsem to vyzkoumal takto:
Pokud je druhá hodnota cizí klíč (resp. sloupec je „parent_id“ a já
uvedu „parent“), tak fetchPairs všechny cizí klíče fetchne a pole
obsahuje rovnou ActiveRow. To je dobře. Ale v Nette 2.0 se provede 1 x
SELECT .. IN (všechny hodnoty cizích klíčů), zatímco v Nette 2.1 se ten
stejný SELECT provede tolikrát, kolik těch cizích klíčů je. A to není
úplně dobře.
- kolsi
- Člen | 131
Ještě se zeptám takhle – když je getReferencedTable tedy privátní metoda (ačkoli to nikde není uvedeno), tak pokud mám 2 tabulky (např. projects a users) spojené vazbou M:N (mám tedy spojovací tabulku projects_users), jak tedy optimálně (= co nejmenší množství dotazů + co nejrychleji + co nejméně kódu) vytáhnu data z jedné tabulky pro hodnotu z druhé tabulky?
Např. chci všechny projekty pro uživatele s ID $user_id. Nyní dělám:
$this->connection->table("projects_users")->where("user_id", $user_id)->getReferencedTable("projects", "project_id");
Předpokládám, že Nette vytvoří pouze jeden dotaz a vrátí mi Selection obsahující všechny vyhovující záznamy z tabulky „projects“. Pokud místo getReferencedTable() použiju related():
$this->connection->table("users")->get($user_id)->related("projects_users", "user_id")
Tímto ale dostanu Selection obsahující záznamy z tabulky projects_users a pak musím volat ještě $record->project->…, což mi vytvoří další dotazy navíc.
Takže dotaz je jasný.
- norbe
- Backer | 405
A proč porovnáváš 2 různé věci?
Jednou vycházíš z tabulky projects_users
a podruhé z
users
. Osobně bych použil ten druhý kód, schválně se
podívej, kolik ti ten dotaz navíc sežere času…
Pokud chceš nejefektivněji získat projekty daného uživatele uděláš to
takhle:
$this->connection->table('projects')->where(':projects_users.user_id', $userId)
.
- kolsi
- Člen | 131
První případ je, jak to děláme teď. Ten druhý jsem sestavil teď narychlo podle dokumentace s využitím „related“ (jak radil hrach o pár příspěvků výše). related se musí volat nad ActiveRow, proto jsem vyšel z jiné tabulky.
Každopádně jednoduché vypsání názvu všech projektů je s „related“ skoro 2× pomalejší než s getReferencedTable. Ale tvůj návrh vypadá použitelně, protože je zase naopak asi 2× rychlejší než getReferencedTable :) Ještě musím projít, jestli to půjde použít ve všech našich případech a pokud jo, tak problém bude vyřešen. Díky!