Ci sono diversi modi in cui è possibile accedere al repository dell'entità nei controller o nei servizi Symfony2, ciascuno dei quali ha il proprio vantaggio e svantaggio. Per prima cosa li elenco qui, e poi chiedendo se c'è qualche soluzione migliore o queste sono le uniche opzioni che abbiamo e dovremmo scegliere uno o alcuni in base alle nostre preferenze. Voglio anche sapere se il metodo 5 (che ho iniziato a usarlo di recente) può essere buono e non infrange nessuna regola o ha effetti collaterali.Symfony - Come accedere al repository dell'entità
Metodo di base: Utilizzare il gestore entità nel controller o Iniettarlo su un servizio e quindi accedere a qualsiasi repository che desidero. Questo è il modo di base per accedere a un repository nel controller o nel servizio.
class DummyController
{
public function dummyAction($id)
{
$em = $this->getDoctrine()->getManager();
$em->getRepository('ProductBundle:Product')->loadProduct($id);
}
}
Ma ci sono alcuni problemi relativi a questo methos. Il primo problema è che non posso fare Ctrl + clic sulla funzione loadProduct ad esempio e andare direttamente alla sua implementazione (a meno che non ci sia un modo che non conosco). L'altro problema è che finirò per ripetere questa parte di codice più e più volte.
Metodo 2: L'altro metodo è solo per definire un getter nel mio servizio o controller per accedere al mio repository.
class DummyService
{
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function dummyFunction($id)
{
$this->getProductRepository()->loadProduct($id);
}
/**
* @return \ProductBundle\Entity\Repository\ProductRepository
*/
public function getProductRepository()
{
return $this->em->getRepository('ProductBundle:Product');
}
}
Questo metodo risolve il primo problema e in qualche modo il secondo, ma ancora devo ripetere tutti i getter che ho bisogno nel mio servizio o del controller, anche avrò parecchi getter nei miei servizi e controller solo per l'accesso al repository
Metodo 3: un altro modo è quello di iniettare un repository per il mio servizio, è bello, soprattutto se abbiamo un buon controllo sul nostro codice e non siamo coinvolti con altri sviluppatori che si iniettano l'intero contenitore al tuo servizio.
class DummyService
{
protected $productRepository;
public function __construct(ProductRepository $productRepository)
{
$this->productRepository = $productRepository;
}
public function dummyFunction($id)
{
$this->productRepository->loadProduct($id);
}
}
Questo metodo risolve il primo e il secondo problema, ma se il mio servizio è grande e ha bisogno di fare con un sacco di repository, allora non è una bella idea di iniettare per esempio 10 repository al mio servizio .
Metodo 4: Un altro modo è disporre di un servizio per includere tutti i miei repository e iniettare questo servizio su altri servizi.
class DummyService
{
protected $repositoryService;
public function __construct(RepositoryService $repositoryService)
{
$this->repositoryService = $repositoryService;
}
public function dummyFunction($id)
{
$this->repositoryService->getProductRepository()->loadProduct($id);
}
}
RepositoryService:
class RepositoryService
{
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
/**
* @return \ProductBundle\Entity\Repository\ProductRepository
*/
public function getProductRepository()
{
return $this->em->getRepository('ProductBundle:Product');
}
/**
* @return \CmsBundle\Entity\Repository\PageRepository
*/
public function getPageRepository()
{
return $this->em->getRepository('CmsBundle:Page');
}
}
Questo metodo risolve anche il primo e secondo problema. Ma RepositoryService può diventare così grande quando abbiamo 200 entità ad esempio.
Metodo 5: Infine, è possibile definire un metodo statico in ogni entità che restituisce il proprio repository.
class DummyService
{
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function dummyFunction($id)
{
Product::getRepository($this->em)->loadProduct($id);
}
}
mio Entity:
/**
* Product
*
* @ORM\Table(name="saman_product")
* @ORM\Entity(repositoryClass="ProductBundle\Entity\ProductRepository")
*/
class Product
{
/**
*
* @param \Doctrine\ORM\EntityManagerInterface $em
* @return \ProductBundle\Entity\ProductRepository
*/
public static function getRepository(EntityManagerInterface $em)
{
return $em->getRepository(__CLASS__);
}
}
Questo metodo risolve il primo e il secondo problema anche non ho bisogno di definire un servizio per accedere ai repository. L'ho usato di recente e finora è il metodo migliore per me.Non penso che questo metodo infrangerà la regola delle entità poiché è definita nello scope della classe ed è anche così. Ma ancora non ne sono sicuro e se ha o meno effetti collaterali.
Uso i servizi per i miei archivi con interfacce. Riduce la quantità che il mio codice è direttamente accoppiato con Doctrine quando non è realmente necessario. Tutto ciò che un servizio/oggetto richiede è che ottiene un repository che si adatta all'interfaccia invece di ottenere Doctrine, per ottenere il repository (che non è anche controllato da un tipo, quindi potrebbe non avere alcun metodo personalizzato). – qooplmao
Non hai assolutamente bisogno di dottrina. È come avere una mucca, quando tutto ciò di cui hai bisogno è un po 'di latte. – user2268997
hai ragione @ user2268997 – Roukmoute