Cizí klíče nefungují (konvence dodržuji)

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

Verze Nette: 2.0.3-PHP5.3

Vytvořím si DB a příslušné tabulky:

SET NAMES utf8;
SET foreign_key_checks = 0;

CREATE DATABASE IF NOT EXISTS `nette` CHARACTER SET = utf8;

/* Přesunu se do právě vytvořené DB nette */
USE `nette`;

/* Vytvoř uživatele nette s heslem nette */
CREATE USER 'nette'@'%' IDENTIFIED BY 'nette';

/* Uživatel nette dostane všechny práva pro DB nette */
GRANT ALL ON `nette`.* TO 'nette' ;

CREATE TABLE `users` (
        `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
        `nick` varchar(10) NOT NULL,
        `password` char(128) NOT NULL,
        `name` varchar(10),
        `surname` varchar(15),
        `datum` datetime NOT NULL,
        PRIMARY KEY (`id`),
        UNIQUE KEY `nick` (`nick`)
) ENGINE=InnoDB;

CREATE TABLE `category` (
        `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
        `category_id` int(10) unsigned NOT NULL,
        `title` varchar(12) NOT NULL,
        `description` varchar(150),
        PRIMARY KEY (`id`),
        UNIQUE KEY `title` (`title`),
        INDEX `fk_category2` (`category_id`),
        CONSTRAINT `fk_category2` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`)
) ENGINE=InnoDB;

CREATE TABLE `post` (
        `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
        `users_id` int(10) unsigned NOT NULL,
        `title` varchar(20),
        `datum` datetime NOT NULL,
        `text` varchar(150),
        `category_id` int(10) unsigned NOT NULL DEFAULT 1,
        PRIMARY KEY (`id`),
        INDEX `fk_users` (`users_id`),
        INDEX `fk_category` (`category_id`),
        CONSTRAINT `fk_users` FOREIGN KEY (`users_id`) REFERENCES `users` (`id`),
        CONSTRAINT `fk_category` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`)
) ENGINE=InnoDB;

FLUSH PRIVILEGES;

V Admineru vidím správně schéma i cizí klíče.

Tabulka sama se vypíše v pořádku. Nicméně cizí klíč již ne, např:

{var $title = "Posts"}
{block content}
{if count($posts) > 0}
        {foreach $posts as $post}
        <h2>{$post->title}</h2>
        <span class="author">Autor: {$post->users_id->nick}</span>
        <span class="category">Kategorie: {$post->category_id}</span>
        <span class="date">Vytvořeno: {$post->datum}</span><br />
        {!$post->text}
        {/foreach}
{else}
 <p> Nejsou žádné příspěvky</p>
{/if}

Vyhodí (Laďenka):

Notice

Trying to get property of non-object

Jsou ještě nějaká další pravidla pro to, aby mi propojení tabulek fungovalo?

Už jsem zjistil, že potřebuji ENGINE=InnoDB a cizí klíč pojmenovat „tabulka_id“, kde tabulka je jméno tabulky na kterou se odkazuji.

Prošel jsem tyto vlákna
https://forum.nette.org/…tte-database
https://forum.nette.org/…edreflection

A nepomohlo to.

Připojuji se k DB dle Quickstartu (factory, v modelu třída pro každou tabulku).

Editoval kedrigern (20. 5. 2012 2:25)

duke
Člen | 650
+
0
-

Předpokládám, že používáš DiscoveredReflection.
Myslím, že když místo {$post->users_id->nick} použiješ {$post->user->nick}, že to pojede. Mělo by fungovat i {$post->users->nick}. Zápis {$post->users_id} je nejspíš rezervován pro přístup k hodnotě toho sloupce users_id, i když v jednom z odkazovaných příspěvků tam Hrach uvádí, že i to by mělo fungovat… (ale to je 5 měsíců starý komentář, takže může být již neaktuální)

Editoval duke (20. 5. 2012 3:06)

ViPEr*CZ*
Člen | 817
+
0
-

No je to vidět přímo v dokumentaci: https://doc.nette.org/cs/database

kedrigern
Člen | 102
+
0
-

duke> No právěže jsem z toho dost zmaten. Ne že bych nehledal, ale spíš vyznat se v tom, co je platné, není rozbité a podobně není úplně triviální. Proto už se ani neptám na chybu, al na ty podmínky (ono najít je všechny pohromadě také není lehké).

Už to funguje! Tyto tři zápisy ozkoušeny:

<span class="author">Autor: {$post->ref('users_id')->nick}</span>
<span class="author">Autor: {$post->user->nick}</span>
<span class="author">Autor: {$post->users->nick}</span>

Nesmí se tam přímo uvádět název té reference.

Děkuji moc, jak se Nette teprve učím, tak občas přehlížím detaily, protože jsem si prostě nejistý, kde co může být špatně.

PS: značí se tu nějak vyřešená vlákna?

Editoval kedrigern (20. 5. 2012 13:09)

ViPEr*CZ*
Člen | 817
+
0
-

Používal bych asi toto $post->users->nick kdy je vidět, že se ta tabulka jmenuje users a ne user, jak by se mohlo zdát z druhého zápisu.

jtousek
Člen | 951
+
0
-

ViPErCZ napsal(a):

Používal bych asi toto $post->users->nick kdy je vidět, že se ta tabulka jmenuje users a ne user, jak by se mohlo zdát z druhého zápisu.

Já bych zase tu tabulku pojmenoval user.

EDIT: Tabulku kategorií má také pojmenovanou category a ne categories. Konvence jsou konvence, někdo používá jednotné číslo, někdo množné. Moje preference je používat jednotné. Ale rozhodně není dobrý nápad to míchat.

Editoval jtousek (20. 5. 2012 13:51)

ViPEr*CZ*
Člen | 817
+
0
-

jtousek napsal(a):

ViPErCZ napsal(a):

Používal bych asi toto $post->users->nick kdy je vidět, že se ta tabulka jmenuje users a ne user, jak by se mohlo zdát z druhého zápisu.

Já bych zase tu tabulku pojmenoval user.

EDIT: Tabulku kategorií má také pojmenovanou category a ne categories. Konvence jsou konvence, někdo používá jednotné číslo, někdo množné. Moje preference je používat jednotné. Ale rozhodně není dobrý nápad to míchat.

Naprosto souhlasím. Také používám jednotná čísla. Ale je to prakticky jedno, ať si dotyčný vybere. Jen jak jsi psal… míchat to se nevyplácí. ;-)

kedrigern
Člen | 102
+
0
-

Jo, jenže když se použije jednotné číslo, tak dostanu:

Nette\DI\ServiceCreationException

It is not allowed to use service and factory with the same name 'user'.

A teď zkoumám, kde se přesně a jak definuje ten defaultní servise user (pracuji nad sandboxem).

Proto jsem to zatím nepoužíval, protože jsem si nejdřív chtěl vyzkoušet základy.

castamir
Člen | 629
+
0
-

Nette/Security/User a po autentifikaci se mu navíc přiřadí údaje z Identity. Nezkoumal jsem to zrovna důkladně, ale předpokládám, že je to jedna z implicitních služeb…

Editoval castamir (20. 5. 2012 18:43)

kedrigern
Člen | 102
+
0
-

Jo já to vidím, jen ještě nevím jak to použít.

A jak vyřešit konflikt jmen. Nejednodušší je asi nedefinovat továrnu pro user, avšak ještě nevím jak si je pak třeba vypsat ad hoc.

Prostě je toho pro mě dost nového.

Edit: Je někde popis jak používat Services? Továrnu jsem pochopil z quickstartu. Service je „jakási perzistentní továrna“, avšak nevím co třeba ta předdefinovaná umí.

Edit2: Tak jsem továrnu přejmenoval na „userfactory“, protože servis jsem neuměl využít stejně jako továrnu (například, když chci vypsat všechny uživatele). Kdybyste mi někdo poradil, jak používat servis, tak budu rád.

Editoval kedrigern (20. 5. 2012 21:15)