Bezbolestná integrace Doctrine 2 ORM do Nette – Kdyby/Doctrine

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

Počkej, jakto že nejde?

/**
 * @ORM\Entity
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="author_type", type="string")
 * @ORM\DiscriminatorMap({
 * 		"guest"		= "Guest",
 * 		"system"	= "System",
 * 		"facebook"	= "Facebook",
 * 		"twitter"	= "Twitter",
 * 		"google"	= "Google",
 * 		"github"	= "Github"
 * })
 */
class Guest extends \IPub\Doctrine\Entity implements Comments\IAuthor
{
	//...
}
/**
 * @ORM\Entity
 */
class Comment extends \IPub\Doctrine\Entity implements IComment, Comments\IComment
{
	/**
	 * @var \IPub\Comments\Entities\IAuthor
	 * @writable
	 *
	 * @ORM\ManyToOne(targetEntity="IPub\CollectionsModule\Entities\Comments\Authors\Guest", cascade={"persist"})
	 * @ORM\JoinColumn(name="author_id", referencedColumnName="author_id", onDelete="CASCADE")
	 **/
	protected $author;
}

a načtou se mi jednotlivé entity podle sloupce. Nebo chceš něco jiného?

mkoubik
Člen | 728
+
0
-

Climber007 napsal(a):

Vždycky chci buď rodiče nebo potomky s atributy rodiče.

Tak tohle samozřejmě jdem – to je klasická dědičnost. Máš třeba třídu User, od které dědí třídy Customer a Admin. Pak můžeš načíst objekt třídy Customer včetně dat z třídy User, dokonce i objekt třídy User, pokud není abstraktní, ale nemůžeš načíst objekt, který (což jsem vyrozuměl že požaduješ) obsahuje data z Customer a Admin zároveň (jaká třída by to byla?).

Climber007
Člen | 105
+
0
-

mkoubik napsal(a):

Climber007 napsal(a):

Vždycky chci buď rodiče nebo potomky s atributy rodiče.

Tak tohle samozřejmě jdem – to je klasická dědičnost. Máš třeba třídu User, od které dědí třídy Customer a Admin. Pak můžeš načíst objekt třídy Customer včetně dat z třídy User, dokonce i objekt třídy User, pokud není abstraktní, ale nemůžeš načíst objekt, který (což jsem vyrozuměl že požaduješ) obsahuje data z Customer a Admin zároveň (jaká třída by to byla?).

Chci buď Customer nebo Admin s daty z User. Problém je, že do toho diskriminatoru jde nacpat pouze jedna z entit, nikoliv nějaká kolekce 2 a víc možných potomků.

akadlec
Člen | 1326
+
0
-

Single table inheritance jak jsem ukazoval výše ne? Customer a Admin budou dědit od User a je to ne?

Climber007
Člen | 105
+
0
-

akadlec napsal(a):

Single table inheritance jak jsem ukazoval výše ne? Customer a Admin budou dědit od User a je to ne?

Jenže to mi nedovolí mít k jednomu User jednoho Admin a zároveň Customer. Nebo snad jo? Zkoušel jsem všechny možnosti a nic.

mkoubik
Člen | 728
+
0
-

Ten admin a customer jsou dva různé objekty, takže jsou reprezentovány 2 řádky v tabulce. Pokud mají data z třídy User stejná, tak to v db prostě bude dvakrát. Pokud potřebuješ ta data v User sdílet mezi více objekty, tak to není dědičnost, ale kompozice.

Tzn, Customer a Admin by neměli od User dědit, ale místo toho dostat objekt třídy User např. v konstruktoru a plácnout ho do ManyToOne vazby.

Edit: Skus přesněji popsat čeho se snažíš dosáhnout. Všechno co se dá vyjádřit v php pomocí OOP, dědičnosti a kompozice se dá pomocí doctrine namapovat do db, opačně to jít nemusí. Napiš proto jak bys to chtěl řešit v php. Představ si že žádnou db nemáš a místo repository ukládáš/načítáš ty entity do/z asociativního pole podle id.

Editoval mkoubik (16. 5. 2014 14:27)

Climber007
Člen | 105
+
0
-

mkoubik napsal(a):

Ten admin a customer jsou dva různé objekty, takže jsou reprezentovány 2 řádky v tabulce. Pokud mají data z třídy User stejná, tak to v db prostě bude dvakrát. Pokud potřebuješ ta data v User sdílet mezi více objekty, tak to není dědičnost, ale kompozice.

Tzn, Customer a Admin by neměli od User dědit, ale místo toho dostat objekt třídy User např. v konstruktoru a plácnout ho do ManyToOne vazby.

Díky moc za objasnění, přesně to jsem myslel! Potom už mi to došlo, že to dědičnost není a musím to řešit jinak.

Edit: Už to mám pomocí bidirectional OneToOne, kde vazba „potomků“ (Customer, Admin) k „rodiči“ (User) je EAGER a obráceně je LAZY. Mám jednoduše potřebu uchovávat k více uživatelským rolím další informace než k obyčejnému User, kde jsou jen ta nejdůležitější data (username, pass, fullname). KDyž pracuji s „potomky“, chci mít přístup k těm datům nahoře, ale obráceně budu data tahat jen v minimu případů (proto LAZY). Snad je to tak optimální řešení.

Editoval Climber007 (16. 5. 2014 14:33)

sasule
Člen | 18
+
0
-

Ahoj,
měl bych tu drobný problém s cachováním do memcache.
Mám dva weby na jednom serveru, nastavil jsem cachování dle návodu:

doctrine:
    metadataCache: memcache(@memcache.client)
    queryCache: memcache(@memcache.client)
    resultCache: memcache(@memcache.client)
    hydrationCache: memcache(@memcache.client)

services:
    memcache.client:
        class: Memcache()
        setup:
            - addserver(localhost, 11211)

V obou webech používám objekt Sasule\Entities\User, který ale v případě jednom má závislost na Sasule\Entities\Bank a ve druhém ne. Podotýkám, že weby jsou na sobě nezávislé, každý má svou databázi, jen běží na jednom fyzickém stroji.

První web spustím, vše OK, když poté spustím druhý, dostávám výjimku:
Kdyby\Doctrine\MissingClassException, která říká, že Sasule\Entities\Bank nebylo nalezeno (ani nemohlo, ve druhém webu prostě není).

Tož, přemýšlím, co s tím? Protože předpokládám, že stejně se to bude chovat i kdekoli jinde.

Neexistuje třeba nějaké nastavení pro Memcache, kde by se vynutil nějaký „namespace“ pro cachovaná data?

Díky za případné rady.

Jiří Nápravník
Člen | 710
+
0
-

Co koukám tak Nettí memcached přijímá v kontruktoru i prefix

sasule
Člen | 18
+
0
-

Díky, po chvilce zápasu mi to pomohlo!

Climber007
Člen | 105
+
0
-

akadlec napsal(a):

@Filip Procházka: Díky tohle již funguje. K původní save metodě sem si přidal saveAll která provede save a flushne celý EM

Sice je to už dlouho, ale potřeboval bych jen potvrdit. Jestli není jiný řešení:
Pokud mám One-To-One a potřebuji ukládat i změny v té druhé entitě, je vhodný v service třídě s předaným DAO volat metodu saveAll() namísto save():

public function saveAll(\App\Entities\IdentifiedEntity $entity)
{
    return $this->dao->getEntityManager()->flush();
}

Je to nejlepší řešení nebo je lepší sahat přímo na EM a persist() a flush() metody? Nevadí, že budu tohle používat pořád namísto save()? Kde by mohli v takovém případě nastat problémy?

Díky moc!
PS: Sorry, ale příště už to půjde přes help.kdyby.org ;-)

Editoval Climber007 (31. 5. 2014 17:50)

Tomáš Votruba
Moderator | 1114
+
0
-

Predej si rovnou entity manager a na nem volej flush(). Nema smysl jej nekam schovavat.

Climber007
Člen | 105
+
0
-

Filip Procházka napsal(a):

Četl jsi tohle?

Četl, ale lehce jsi to změnil od poslední návštěvy někdy v dubnu. Teď už je mi to jasný. Díky!

Filip Procházka
Moderator | 4668
+
0
-
Filip Procházka
Moderator | 4668
+
0
-

Další otázky prosím zakládejte jako samostatná témata na novém fóru help.kdyby.org. Díky!