doctrine 2 – sandbox a jak dál
- Filip111
- Člen | 244
Ahoj, začínám se poohlížet po doctrine2 – čerpám hlavně z:
https://forum.nette.org/…-nette-2-0-x
https://forum.nette.org/…-containerem
Prošel jsem si i oba sandboxy od HosipLana i Patrika Votočka…stále ale
nevím jak začít. Je toho zkrátka nějak moc najednou (podobně jako když
jsem začínal s Nette :)
Oba sandboxy krásně naběhly, ale co dál? Opravdu nevím jak začít –
kam co napsat.
Hrozně by mi pomohla ukázka, kde bude nějaký sandbox rozšířený alespoň
o jednu tabulku, entitu apod., kde se do šablony předá třeba jedna řádka
z databáze.
Poslalo by mě to správným směrem, abych nedělal nějaký prasárny,
kterých bych se nedejbože nějaký měsíc držel a pak to přepisoval.
Nemáte odkaz na nějaký takový sandbox nebo jinou ukázku? (článek, diskusi?) Všechny články co jsem zatím viděl skončily u vytvoření funkčního prostředí Nette + Doctrine2 a právě ten první (resp. další) krůček tam chybí.
Díky.
- Aurielle
- Člen | 1281
Můžeš se inspirovat HosipLanovým DAO – http://www.aceblog.cz/…-dava-smysl/. Nebo prostě zkusit v presenteru něco jako:
public function renderDefault()
{
// způsob přístupu k EM si upravíš podle toho, jaký sandbox použiješ...
$this->template->data = $this->context->doctrine->entityManager->getRepository('User')->findBy(array('active' => TRUE));
// nebo - DQL - vykopírováno z jednoho projektu
$query = $this->context->doctrine->entityManager->createQuery('SELECT e, r, a FROM AvalonProject\Entities\FairyTail\Episode e
LEFT JOIN e.subtitles r LEFT JOIN e.arc a ORDER BY e.isOva ASC, e.aired DESC');
$this->template->episodes = $query->getResult();
}
<ul n:inner-foreach="$data as $user">
<li>{$user->name}</li>
</ul>
Entity si ukládej kam chceš, hlavně je Doctrine musí najít. Já je mám třeba v %appDir%/entities…
- Filip111
- Člen | 244
Dokumentaci samotnou jsem zatím jen prolítnul, pročítal jsem seriál na
zdrojáku.cz.
Osobně mi samotná dokumentace zatím moc nedá – je tam jen spousta nových
pojmů, které se mi jen pletou dohromady.
Až když si to sám vyzkoušim, začne se to v hlavě třídit a dokážu si
pod slovem entity mapper a spoustou dalších pojmů představit něco
konkrétního. Pak je čas pročíst dokumentaci pořádně :)
Něco mi sandbox už dělá…brzy se zase vrátím s nějakým „obrovským“ problémem.
- awsickness
- Člen | 98
co se tyce doctrine je tam celkovy problem jak to co nejlepe resit. co clovek
to vlastni pristup.
osobne se rozhoduji jakou cestou pujdu.
jestli bude „dataobject“ ten zabalim do repository aby se nemichaly data a
funcionalita nad nima.
dalsi pohled je
mit entitu a ta by mela umet sama nad sebou pracovat ?
nejvic se mi libi myslenka mit entitu na ni volat vse
$entity->callSomeQuery();
a uvnitr by mohla byt jakakoliv implementace napriklad i ta hospilanova.
jediny problem je ze jsem nenasel misto kde dane entity podstrcit entityManager :/
- Filip Procházka
- Moderator | 4668
Já bych ti doporučil si přečíst tyto výživné diskuze
https://forum.nette.org/…-orm-pro-php#…
https://forum.nette.org/…ny-na-notorm
Jenom bych doporučil ignorovat ty doporučení ohledně vnořených containerů, to se ukázalo jako anti-pattern ;)
Editoval HosipLan (11. 1. 2012 17:01)
- mkoubik
- Člen | 728
awsickness napsal(a):
dalsi pohled je mit entitu a ta by mela umet sama nad sebou pracovat ?
To potom není ORM, ale Active Record ($entity->save()
etc.),
kterej IMHO porušuje SRP a pokud nepoužíváš jazyk, kterej se na tohle hodí
(ruby, smalltalk), tak se lehce dostaneš do problémů (třeba při
testování).
- awsickness
- Člen | 98
mkoubik: to ja vim taky pisu ze by se mi to sice nejvic libilo ale jen takove
logicke uceleni.
ted to delam jinak a chystam se to udelat uplne jinak :) ale co je nakonec best
practise to asi nikdo nerekne.
- Filip111
- Člen | 244
@HosipLan: obě diskuse už jsem v minulosti četl…a teď zase.
Výsledek je, že z toho mam akorát depku :)
Mj. jsi tam kritizoval mít různý model pro administraci a různý pro
frontend, což používám.
V modelu pro frontend jsou klasické metody jako getOne, getAll apod., které
vytahují téměř připravená data z DB view.
V administraci mám basemodel s metodami insert, update, delete apod. které
automaticky podle struktury tabulky generují sql dotazy. Zjišťuji tam
struktury tabulek v DB a případně rozložím data z formuláře do více
tabulek (typicky hlavička a jazykově závislá data) apod.
Hlavní je, že se v té admin části občas začínám ztrácet, často to
musím stejně přepsat pro konkrétní model a občas je to WTF.
Tohle je něco, kde si slibuju od doctrine výrazné usnadnění díky
mapování a propojení entit. Naprostá většina dat se skládá z tabulky
pro hlavičku a z tabulky pro jazykově závislé texty, kde může být
k jedné hlavičce více záznamů pro různé jazyky.
Otázka 1:
Pokud chápu asociace, tak samotná entita Zbozi bude napojená na další
entity podobně jako jsou spojené přes foreign keys v DB? Výsledkem tedy
bude hromada navzájem propojených entit (v kterých se po čase člověk taky
ztratí).
Chci se zeptat na tvoření entit – konkrétně pro zboží. Informace o zboží jsou rozprsklé asi ve 20ti tabulkách – základní informace, parametry, varianty, obrázky, přílohy, historie cen apod., většina vícejazyčně.
Otázka 2:
Lze Zbozi (tedy dvě základní tabulky – hlavičku a texty) definovat jako
jednu entitu nebo musím jako dvě Zbozi a ZboziText ? Pracovat budu vždy se
zbožím jako jedním objektem a při uložení budu chtít aby se to do těchto
tabulek „samo“ rozdělilo…na jaké by to mělo být úrovni? Repository
nebo ještě výš?
Díky.
- Filip Procházka
- Moderator | 4668
@**Filip111**: Pokud chceš začít dělat s ORM, musíš přestat uvažovat v tabulkách a začít uvažovat v objektech. Dává smysl, aby tahle entita měla vazbu na tuhle entitu a tohle se předávalo tady, … Tabulky tě už nezajímají, jsou někde na pozadí, stará se o ně ORM a to automaticky.
Co se týče zboží, nejsem si jistý jestli chápu o co ti jde. Ty totiž předpokládáš, že budeš mít tabulku a ta bude mít relaci na druhou tabulku, ale z tabulek objekty neuděláš.
Takže já ti taky položím otázku: Proč? Rozmysli se co chceš, co to má dělat, jaký to má mít výsledek. Né jak to má být implementované. Pak ti možná budu schopný říct, jak bych to řešil.
- Patrik Votoček
- Člen | 2221
awsickness napsal(a):
mit entitu a ta by mela umet sama nad sebou pracovat ?
To je případ Doctine ORM 1 kdy to bylo postavené jako Active Record
Doctrine ORM 2 je naopak postaveno na Data Mapperu.
Snažit se Doctrine ORM 2 ohýbat na Active Record je tak trochu drbání se levou nohou za pravým uchem.
mkoubik napsal(a):
To potom není ORM, ale Active Record …
bullshit… AR je taky ORM taky to mapuje objekty s relacema… :-)
Filip111 napsal(a):
… Mj. jsi tam kritizoval mít různý model pro administraci a různý pro frontend, což používám.
Pokud je tím myšlen model jako celek tak je to špatně. Pokud je tím myšlena určitá část (manipulace s datama) tak tam to smysl dává.
Sám ve starších projektech používám dělení Repository vs. Service viz několik článků:
Otázka 1: … Otázka 2: …
Na obě otázky se dá odpovědět zároveň. V tomhle je právě síla ORM a nejtěžší věc na naučení. Musíš přestat nad daty uvažovat jako o tabulkách v DB. Musíš o nich uvažovat jako o entitách.
Entity ti totiž umožní třeba tohle: http://www.doctrine-project.org/…mapping.html :-)
- Filip111
- Člen | 244
Já zatím opravdu nevím co chci/co dál :(
Pročetl jsem dneska většinu českého internetu zmiňující Doctrine2,
k tomu samozřejmě argumenty Doctrine2 versus notORM/Dibi a vůbec všechno co
jsem našel v cz.
Samozřejmě jsem nezapomněl ani na dokumentaci Doctrine2 a pár anglických
článků.
Když bych Doctrine2 použil, potřeboval bych pracovat s vícejazyčnými
entitami…několikrát jsem narazil na názor, proč to vymýšlet, když už
je to vyřešené v Gedmo.
Pak jsem si vzpětí přečetl článek o tom, jak je špatné masivně
používat frameworky a ještě je rozšiřovat o další frameworky a
rozšíření třetích stran apod.
Výsledkem je, že bych s Doctrine2 rád začal, ale nevím jak jednoduše vyřešit elementární věci např. vytvoření entity článku, který je vícejazyčný apod.
Také se děsím propojení, které je nyní v libs a především údržby
do budoucna…Nette, Doctrine, Kdyby, Symphony k tomu možná Gedmo (nebo
Nella..abych nezapomněl :).
To je přece šílený – chvilku nebudu koukat na změny ve vývoji a při
nejbližším updatu jedné z komponent/frameworku se to rozsype jak domeček
z karet (anebo u toho budu týden sedět jen abych to zase na pár měsíců
rozhýbal).
Možná to dopadne jako s Nette…půl roku o tom budu uvažovat, pak to zkusím, první měsíc budu přepisovat pořád dokola stejný kódy aby byly lepší a lepší a nakonec budu rád že jsem se to naučil a začal používat.
Editoval Filip111 (12. 1. 2012 21:28)
- Filip Procházka
- Moderator | 4668
Well, Kdyby není ready na produkci, takže je to zatím spíše na hraní ;)
Co se týče Doctrine 2, tak ta se zase tak moc nemění a docela si i drží zpětnou kompatibilitu a mají dobrý changelog.
Ohledně více frameworků, já mám na projektu teď 4 frameworky a asi 7 dalších knihoven :) Hrůzné, že? Ani ne, protože je nikdy nepoužívám v jeden moment všechny zároveň. Vždycky jen co se týká jedné části aplikace.
- Filip111
- Člen | 244
Jsem zatím ve fázi zkoušení Doctrine a hledání řešení konkrétních úloh. S čím si nevím rady po prostudování dokumentace a shlédnutí několika screencastů je vícejazyčnost. Chtěl bych to zkusit bez Gedmo rozšíření – především, protože se tu o něm moc nemluví (neví?) a nechci zbytečně zanášet do projektu další závislost na nějakém rozšíření.
Konkrétně: potřebuji vytvořit entitu Categories, která bude mít vlastnosti id a status a potom jazykově závislé lang a title.
Nevím jak toho docílit – zatím se mi podařilo vytvořit entitu, která není plochá ale má id, status a texts což je pole hodnot lang a title.
/**
* @Entity
* @Table(name="eshop_categories")
*/
class Categories extends \Nette\Object
{
public function __construct()
{
$this->texts = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* @id @column(type="integer")
* @generatedValue
*/
private $id;
/* @column(type="boolean") */
private $status;
/**
* @var CategoriesText
* @OneToMany(targetEntity="CategoriesText", mappedBy="eshop_categories_text", cascade={"persist"})
*
*/
private $texts;
}
/**
* @Entity
* @Table(name="eshop_categories_text")
*/
class CategoriesText extends \Nette\Object
{
/**
*
* Store a reference to the category
* @id
* @column(type="integer", nullable="false")
* @ManyToOne(targetEntity="Categories", inversedBy="texts")
* @JoinColumn(name="id", referencedColumnName="id")
*/
private $id;
/**
* @id @column(type="string")
* @Column(length=2)
*/
private $lang;
/* @column(type="string") */
private $title;
}
Ani ta ale nefunguje správně – když vygeneruji sql dump schámatu, vytvoří to následující SQL:
CREATE TABLE eshop_categories (
id INT AUTO_INCREMENT NOT NULL,
PRIMARY KEY(id)
) ENGINE = InnoDB;
CREATE TABLE eshop_categories_text (
id INT NOT NULL,
lang VARCHAR(2) NOT NULL,
PRIMARY KEY(id, lang)
) ENGINE = InnoDB
1) Nevíte proč tam chybí polovina sloupců definovaných
v entitě?
2) Za předpokladu, že se smířím s tím, že texty budou
pro entitu Categories přístupné přes vlastnost texts, je deklarace této
entyty správně?
3) Jak bych měl definovat entity Categories, abych dostal
plochou strukturu, id, status, lang, title?
pro názornost jsem vyházel set a get metody a spoustu polí.
Díky.
- Filip Procházka
- Moderator | 4668
PhpDoc komentáře začínají /**
, né /*
Co se týče těch jazyků, na to je v Doctrine 2 nová feature, filtry na dotazy. Není ale ještě zdokumentovaná.
- Filip111
- Člen | 244
ad 1) aha, hvězdičky..po opravě to vygeneruje správný sql dump
ad 2) v dokumentaci cli jsem našel akorát generate-entity ale nic co by
entitu jen zkontrolovalo
Nicméně u této otázky mi šlo spíš o kontrolu mojí úvahy –
použití joinu a zvolení vztahu ManyToOne
@HosipLan:
ad 3) Nenašel bys nějaký odkaz, který by mě nasměroval – zkoušel jsem
něco googlit, ale nenašel jsem nic relevantního.
Je to pro mě stěžejní věc bez které se dál nehnu – asi 80% objektů,
které mám v databázi jsou jazykově závislé – mají dělený obsah do
dvou tabulek. Dokud tohle nebudu umět v Doctrine efektivně vyřešit, můžu
na ní (na ně?) zapomenout.
Díky.