There are many ways we can access the entity's repository in Symfony controllers or services which each has its advantage and disadvantage. I list them here first, and then asking if there is any better solution for this task or these are the only options and we should choose one or some based on our preferences. I also want to know if method 5 (which I've started to use it recently) can be good and doesn't break any rule or having any side effects.
Method 1: Inject an entity manager to a service and accessing any repository that I want. This is the basic way of accessing a Repository in controller or service.
class ProductService1
{
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function loadProduct($id)
{
$this->em->getRepository('ProductBundle:Product')->loadProduct($id);
}
}
One problem about this method is that I cannot do Ctrl + click on loadProduct function and go directly to its implementation (Unless there is a way that I don't know). The other problem is that I will end up repeating this part of code over and over.
Method 2: The other method is just to define a getter in my service to access my repository.
class ProductService2
{
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function loadProduct($id)
{
$this->getProductRepository()->loadProduct($id);
}
/**
* @return \ProductBundle\Entity\Repository\ProductRepository
*/
public function getProductRepository()
{
return $this->em->getRepository('ProductBundle:Product');
}
}
This method solves the first problem and somehow the second but still I have to repeat all getters that I need in my services, also I will have several getters in my services just for repositories
Method 3: Another way is to inject a repository to my service, it is nice especially if you have a good control on your code and you are not involved with other developers who inject the entire Container to your service.
class ProductService3
{
protected $productRepository;
public function __construct(ProductRepository $productRepository)
{
$this->productRepository = $productRepository;
}
public function loadProduct($id)
{
$this->productRepository->loadProduct($id);
}
}
This method solves the first and second problem, but if your service is big and it needs to deal with a lot of repositories then it is not a nice idea to inject for example 10 repository to your service.
Method 4: Another way is to have a service to wrap all my repositories and inject this service to my other services.
class ProductService4
{
protected $repositoryService;
public function __construct(RepositoryService $repositoryService)
{
$this->repositoryService = $repositoryService;
}
public function loadProduct($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');
}
}
This method also solves the first and second problem. But RepositoryService can become so big when you have for example 200 entities.
Method 5: Finally we can define a static method in each entity which returns its repository.
class ProductService5
{
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function loadProduct($id)
{
Product::getRepository($this->em)->loadProduct($id);
}
}
My 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__);
}
}
This method solves the first and second problem also I do not need to define a service to access repositories, but I am not yet sure about the side effects of this method. I don’t think this method will break the rule of entity and the fact of having a thine entity since this function is defined in the class scope and also is so thine.
Aucun commentaire:
Enregistrer un commentaire