Problém – No reference found
- Jan P.
- Člen | 5
Ahoj, mám jednoduchou DB viz níže dump, pokud v presenteru zkusím zavolat:
$selection = $this->database->table('contacts')->where('campaigns.id = ?', 1);
vrátí se mi error „No reference found for $contacts->campaigns.“ ačkoliv laděnka informuje, že SQL dotaz na db schéma ten cizí klíč našlo (1 dohledaný záznam v KEY_COLUMN_USAGE pro tabulku contacts).
Pokud zkusím jakoukoliv obměnu, např. odstraním restrikci a zkusím použít projekci a pokusím se vypsat název kampaně (campaigns.name), tak to končí shodným problémem.
Pokud kód v presenteru upravím takto:
$selection = $this->database->table('contacts');
foreach ($selection as $s) {
echo $s->ref('campaigns', 'campaign_id')->name;
}
projde vše bez problémů, díky tomu, že neprobíhá dohledávání reference dle schématu.
Hádám, že problém bude přímo v databázi, buď její verzi nebo blbě definované struktuře, klíčích nebo kombinace všeho. Já tam ale bohužel chybu nevidím:(
Budu vděčný za jakoukoliv pomoc, protože nejsem schopen se pohnout z místa a určitě to bude nějaká blbina, mám na to pech:)
PHP verze: 5.4.19
MySQL verze: 5.5.31
Nette instalováno composerem dle tutoriálu
CREATE TABLE IF NOT EXISTS `campaigns` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) COLLATE utf8_czech_ci NOT NULL,
`status` tinyint(1) NOT NULL,
`created` date NOT NULL
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci AUTO_INCREMENT=5 ;
CREATE TABLE IF NOT EXISTS `contacts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) COLLATE utf8_czech_ci DEFAULT NULL,
`surname` varchar(100) COLLATE utf8_czech_ci DEFAULT NULL,
`email` varchar(100) COLLATE utf8_czech_ci DEFAULT NULL,
`campaign_id` int(11) DEFAULT NULL
PRIMARY KEY (`id`),
KEY `campaign_id` (`campaign_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci AUTO_INCREMENT=5 ;
ALTER TABLE `contacts`
ADD CONSTRAINT `contacts_ibfk_1` FOREIGN KEY (`campaign_id`) REFERENCES `campaigns` (`id`) ON DELETE SET NULL ON UPDATE CASCADE;
Editoval Jan P. (27. 2. 2016 10:03)
- Jan P.
- Člen | 5
F.Vesely napsal(a):
Zkus misto
campaigns.id
dat jednotne cislocampaign.id
.
Perfektní, pomohlo to:)
Chápu správně, že tedy Nette předpokládá nějakou jmennou konvenci na
úrovni db?
Např. že název sloupce cizího klíče musí obsahovat postfix „_id“ (já
to tam původně měl náhodou, jakože intuitivně), ale kdyby se sloupec
nejmenoval „campaign_id“ ale třeba „cid“, co by se stalo?
Editoval Jan P. (27. 2. 2016 13:41)
- F.Vesely
- Člen | 369
Kdyz napises campaign.id
, tak Nette Database hleda FK sloupecek
s nazvy idCampaign, campaignId, capmaign_id a mozna jeste neco jineho, vse
neznam. Takze to neni o tom, jak se jmenuje ta tabulka, ale jak se jmenuje ten
FK. Dava to i smysl, protoze muzes mit dva FK do jedne tabulky, napriklad kdyz
mas zpravu a je od uzivatele pro uzivatele.
- Jan P.
- Člen | 5
OK, zkusil jsem přejmenovat tabulku cizího klíče z „campaigns“ na „my_campaigns“ a PHP upraveno následovně:
$selection = $this->database->table('contacts')->select('contacts.*, my_campaigns.name as campaign_name');
Vyzkoušeno a nefunkční: No reference found for $contacts->my_campaigns
Pokud tam dám ovšem „campaigns.name“ a tabulku přejmenuju zpět na campaigns, funguje to. Mám tedy pocit, že v tomto případě záleži na názvu tabulky v kombinaci s názvem cizího klíče, je tak?
Je to jinak v případě projekce a restrikce? Resp. je někde toto
popsáno, vysvětlováno?
V dokumentaci Nette a tutoriálech pro začátečníka jsem to mimo
jednoduchých příkladů iterace přes ActiveRow a tam volání
->ref(…)->atribut nenašel.
Editoval Jan P. (28. 2. 2016 14:18)
- David Matějka
- Moderator | 6445
zalezi na nazvu sloupecku. Nette hleda sloupecek s FK, ktery obsahuje
substring toho, co si napsal. Takze kdyz se sloupecek bude jmenovat
campaign_id
bude fungovat campaign
nebo treba i
camp
nebo campaign_i
. Tohle teda plati pro „has
one“ relaci. Pro obraceny smer je zas dulezity nazev tabulky. A stejna
pravidla plati jak v select, where apod.
- Jan P.
- Člen | 5
F.Vesely napsal(a):
Jak pisu, nezalezi na tom, jak mas pojmenovanou tabulku, ale na tom, jak si pojmenujes ten FK. Pojmenuj si ho, jak chces, klidne si tam davej s na konec (
campaigns_id
).
OK, jenom se zeptám, jak tedy postupuješ pokud bys měl zadání refaktorovat stávající aplikaci, která už má hromady tabulek, relací, je pojmenovaná na základě toho, jak se předešlej autor před lety vyspal nebo jak moc spěchal a máš zákaz do db jakkoliv sahat. Má smysl vůbec se pokoušet o nasazení Nette resp. použití Nette Database?
- David Matějka
- Moderator | 6445
Má smysl vůbec se pokoušet o nasazení Nette resp. použití Nette Database?
Nette urcite, nette database bych se radeji vyhnul. Mrkni na nejake ORM, treba doctrine nebo nextras/orm