Doctrine a vlastní null objekty

Daewoo
Člen | 33
+
0
-

Ahoj,

jdou nějak v Doctrine 2 řešit null objekty? Triviální příklad: ve stromu kategorií by getParent() neměla vracet pro root hodnotu null ale např. obj. RootCategory. To samé třeba při nějakém listu, kde to bude navíc ještě promíchané (Category a RootCategory).

Pokus o příklad:

interface ICategory
{
	public function getParent();
	public function getId();
	public function getTitle();
}

/** @ORM\Entity */
class Category implements ICategory
{
	/** @return ICategory */
	public function getParent() { return $this->parent; }
	public function getId() { return $this->id; }
	public function getTitle() { return $this->title; }
}

/** @ORM\Entity ??? */
class RootCategory implements ICategory
{
	public function getParent() { return false; }
	public function getId() { return false; }
	public function getTitle() { return 'Root'; }
}

$cats = $em->fetchAll();

dump:

[
	0 => Category [RootCategory, 1, 'prvni uroven'], // prvni uroven, nadrazena kategorie je root
	1 => Category [Category 1, 2, 'druha uroven'], // druha uroven, nadrazena je kategorie s ID 1
	2 => Category [RootCategory, 3, 'opet prvni uroven'] // prvni uroven, nadrazena je opet root
]

Řešit to vnitřní kontrolou v getParent (koneckonců i v setParentu) s tím, že mu pak lazy loadingem předám přes singletona objekt RootCategory (mít třeba 100 stejných RootCategory je nesmysl) mi nepřipadá čistý a cejtim v tom když ne amaterismus, tak aspon potencialni pruser.

V souvislosti s tím mě napadá obecnější otázka (kdyžtak to přehodím do separe vlákna, ale zdá se mi, že princip problému je stejný). Existuje v Doctrine 2 zavedený postup, kdy budou třeba přes list načteny rozdílné (odvozené) objekty? Který z nich se načte je určeno např. v base entitě sloupcem type. Asi to bude souviset i s dalšími věcmi. Vím, že Doctrina umožňuje nějakou formu dědění, ale upřímně se v tom ztrácim a mám v tom tedˇ zmatek.

Pokus o příklad:

abstract class Ovoce // na abstractu netrvám
{
	public function getType(); // je to typ enum
	public function getName();
}

/** @ORM\Entity */
class Svetska extends Ovoce
{
	public function getType() { return 'svestka'; }
	public function getName() { return $this->name; }
}

/** @ORM\Entity */
class Jablko extends Ovoce
{
	public function getType() { return 'jablko'; }
	public function getName() { return $this->name; }
	public function getNumberOfWorms() { return $this->numberOfWorms; } // jablko ma navic jeste dalsi sloupec
}

$fruits = $em->getRepository(Ovoce::class)->fetchAll();

dump:

[
	0 => Jablko [1, 'cervene jablicko', 0],
	1 => Svestka [2, 'svestka na slivovici'],
	2 => Jablko [3, 'jablko s cervy', 12]
]
David Matějka
Moderator | 6445
+
+2
-

ahoj, zacnu odpovedi na obecnejsi otazkou: doctrine podporuje dva zpusoby reseni dedicnosti.

  • tim vice pouzivanym je single table inheritance, kde jsou vsechna data ulozena jen v jedne tabulce (tedy i to numberOfWorms, ktere neni pouzivane u „svestky“)
  • druhym zpusobem je class table inheritance, kde jsou ty odlisna data ulozeny v jinych tabulkach. to ma samozrejme dopad na vykon, proto jsem vzdy pouzival STI

oba zpusoby vyuzivaji tzv diskriminator column, kde je ulozeny typ te entity – tedy jablko nebo svestka

a ted k prvni otazce – jestli se nepletu, tak jedinym zpusobem (mozna existuji nejake extensions? nevim), jak typ te entity rozpoznat, je prave discriminator column a neni tak mozne rozlisit dle toho, zda je nejaka hodnota null nebo ne. takze bys ten discriminator musel na entitu pridat.


dalsi negativni dopady pri pouziti dedicnosti, co me napadaji, tak

  • „to one“ asociace mirici na base tridu (Ovoce) se nenechaji nacitat lazy
  • v dql, pokud vybiras z base tridy, tak nemuzes dat treba do where field, ktery je pouze v child entite – je nutne stejnou tabulku najoinovat jako tu subclass
  • nenecha se snadno zmenit typ entity, tedy treba z root category udelat ne-root
Daewoo
Člen | 33
+
0
-

Děkuju, pochopil a poradil jsem si s tím. STI stačilo a ten null objekt jsem vyřešil prasácky ruční kontrolou v repository (a entitách) – když je null, vyhodím null objekt. Tam se asi aktuálně nic spolehlivýho a bezprůserovýho vymýšlet nedá.