Doctrine v3 one-to-many maping a používání
- jarda256
- Člen | 130
Ahoj, koukal jsem na prezentaci od Filipa Procházky http://www.slideshare.net/…ne-orm-model a další dokumenty o nete a podle toho vytvořil dvě entity (event a site…1 event ma X site) a k nim fasády presenter a další věci, ale nejspíš sem špatně pochopil dokumentaci. Koktrétně mi jde vložení nové strany s vazbou a také sql které mi dá všechy eventy a jejich sites.
- nemělo by v tabulce events existovat pole sites ??
- nemělo by v siteFace stačit $evetn->addsite($element) aby se přidala závislost(MagicAccessors)?
- jak upravit AllEventsQuery.php aby tedy vypisoval eventy a jejich sites? momentálně bere iterátor, který vezme 0 ale za předpokladu, že jsem už předešlé eventy smazal nevezme sites pro event s id 2
- mohu nějak aplikovat paginátor? například abych vypsal 5 eventů s jejich sites na každou stránku
Předem říkám, že jsem entity promazal aby zbylo jen podstaté, proto nesedí doCreateQuery
Pokud jsou otázky hloupě položené, tak se omlouvám a na jakoukoli specifikaci se stačí zeptat. Předem děkuji za odpovědi
Event.php
/**
* @ORM\Entity
* @ORM\Table(name="events")
*/
class Event
{
use Entities\MagicAccessors;
use Entities\Attributes\Identifier;
/**
* @ORM\OneToMany(targetEntity="Site",cascade={"persist","remove"},mappedBy="event")
* @var Site[]|ArrayCollection
*/
protected $sites;
/**
* @ORM\Column(type="string", length=32, nullable=false)
*/
protected $name;
}
Site.php
/**
* @ORM\Entity
* @ORM\Table(name="sites")
*/
class Site
{
use Entities\MagicAccessors;
use Entities\Attributes\Identifier;
/**
* @ORM\ManyToOne(targetEntity="Event", inversedBy="sites")
*/
protected $event;
/**
* @ORM\Column(type="string", length=32, nullable=false)
*/
protected $name;
}
SiteFacade.php
<?php
class SiteFacade extends BaseFacade
{
/**
* @param Event $event
* @param ArrayHash $data
*/
public function createSite(Event $event,$data)
{
$element = new Site();
$element->name = $data->name;
$event->addSite($element);
$this->em->persist($event);
$this->em->flush();
}
}
SitePresenter.php
class SitePresenter extends BaseAdminPresenter
{
/** @var Forms\CreateSiteFormFactory @inject */
public $createSiteFactory;
protected $eventId;
public function actionCreate($id = NULL)
{
$this->eventId = $id;
}
protected function createComponentCreateSiteForm()
{
return $this->createSiteFactory->create($this->eventId,function () {
$this->flashMessage("Strana byla úspěšně vytvořena", 'success');
$this->redirect(':Admin:Event:show');
});
}
}
AllEventsQuery.php
namespace App\Model\Query;
use App\Model\Entities\Event;
use App\Model\Entities\Site;
use Doctrine\ORM\QueryBuilder;
use Kdyby\Doctrine\QueryObject;
use Kdyby\Persistence\Queryable;
class AllEventsQuery extends QueryObject
{
/**
* @param Queryable $repository
* @return QueryBuilder
*/
protected function doCreateQuery(Queryable $repository)
{
return $repository->createQueryBuilder()
->addSelect('partial e.{id,visible,name,date,approve,regCars,optionalItems,note}')
->from(Event::class, 'e')
->orderBy('e.date', 'DESC');
}
public function withSites()
{
$this->onPostFetch[] = function ($_, Queryable $repository, \Iterator $iterator){
$ids = array_keys(iterator_to_array($iterator,TRUE));
$repository->createQueryBuilder()
->select('partial event.{id}', 'sites')
->from(Event::class,'event')
->leftJoin('event.sites','sites')
->andWhere('event.id IN (:ids)')->setParameter('ids',$ids)
->getQuery()->getResult();
};
return $this;
}
}
- akadlec
- Člen | 1326
1. Obousměrná asociace není správná cesta. Zvaž ji mít je
jednosměrnou, tedy jen jedna entita bude vědět o té druhé viz „docka
“:http://docs.doctrine-project.org/…mapping.html
2. Magii se vyhni, je použitelná jen pokud si něco testuješ, ale pak bys
měl entitu zavřít a mít v ní metody co potřebuješ.
3. Stejně jako bys to dělal v SQL, přijoinuješ tu tabulku co ti tam chybí
->join()
4. Ano opět je něco v docce a pokud používáš doctrine přes kdyby tak o tom
máš zmínku v docce tam
- ZahorskyJan
- Člen | 59
@akadlec omlouvám se za vpád do tématu, ale můžeš přidat nějaký zdroj k tomu bodu jedna? Slyším o tom poprvé a v dokumentaci ani v části best practices jsem na to nenarazil. Díky.
- Tharos
- Člen | 1030
@ZahorskyJan Opravdu se o tom píše i v oficiálních best practices:
avoid bidirectional associations if possible
A teď je otázkou, jak chápat to if possible… :)
Jsou tací, kteří se jim vyhýbají jako čert kříži. To mi ale nepřijde úplně dobré, protože se tím mnohdy ochuzují a zbytečně pak musí sahat po různých berličkách, hackovat a elegance je ta tam. Zkrátka občas si situace o obousměrnou asociaci vyloženě říká…
Ale horší je určitě jejich nadužívání, tzn. kdybys například asociace automaticky implementoval jako obousměrné, aniž bys pak obou směrů reálně využíval…
Proč jsou problematické: kladou větší nároky na programátora co se udržení konzistentního stavu týče (v tom pak totiž Doktrína vůbec nijak nepomáhá) a pak se hodně uvádějí jisté výkonnostní důvody.
Taky se uvádí, že přece jenom zvyšují provázání, ale to mi přijde jako takový argument pro argument… :)
Editoval Tharos (4. 12. 2016 23:43)