Problém – No reference found

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

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)

F.Vesely
Člen | 369
+
+2
-

Zkus misto campaigns.id dat jednotne cislo campaign.id.

Jan P.
Člen | 5
+
0
-

F.Vesely napsal(a):

Zkus misto campaigns.id dat jednotne cislo campaign.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)

CZechBoY
Člen | 3608
+
0
-

Prejmenuj teda tabulky na jednotne cislo :-)

F.Vesely
Člen | 369
+
0
-

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.

CZechBoY
Člen | 3608
+
0
-

Podle ceho teda mam urcit jestli psat to S na konci nebo ne?
Pokud bych mel FK na tabulku ASS tak jak bych to mel napsat?

F.Vesely
Člen | 369
+
+2
-

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).

CZechBoY
Člen | 3608
+
0
-

Jo takhle. Takze se orientuju podle nazvu FK a ne nazvu odkazovany tabulky.
Dik :-)

Jan P.
Člen | 5
+
0
-

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

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

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

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

Jan P.
Člen | 5
+
0
-

David Matějka napsal(a):

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

ok, díky za info:)