简体   繁体   中英

Is this a good way to do dependency injection in Symfony2?

I registered my services.yml file like this :

services:
    bb_shop.product_repository:
        class: BB\ShopBundle\Entity\ProductRepository
        factory_service: doctrine.orm.default_entity_manager
        factory_method: getRepository
        arguments: ['BBShopBundle:Product']
    bb_shop.product_service:
        class: BB\ShopBundle\Service\ProductService
        arguments: [@bb_shop.product_repository]

This is my Repository Class :

class ProductRepository extends EntityRepository
{
    public function saveProduct( $p)
    {
        $this->_em->persist($p);
        $this->_em->flush();
    }
}

This My Service Class :

class ProductService {

    protected   $productRepository;
    public  function __construct(ProductRepository $R)
    {
        $this->productRepository =$R;
    }
    public function saveProduct( $p)
    {
        $this->productRepository->saveProduct($p);
    }
} 

And this is how i call my service in the Controller :

 $this->get('bb_shop.product_service')->saveProduct($product);

And All work. my questions are : 1- Can you explain to me why i need this 2 lines even i have the EntityManager in the EntityRepository ( used by $this->_em ) ???

factory_service: doctrine.orm.default_entity_manager
factory_method: getRepository

2 - Is this the good way to do dependency injection ???

  1. You need the two lines because the repository does not extend the entity manager. So basically you are passing persist/flush onto the entity manager. This avoids the need to expose the entity manager to your service. You could inject the manager and call persist/flush directly but really why bother.

  2. I use your approach all the time. So it must be great. As of yet I have not encountered any serious problems.

You should be aware of the side effect of calling saveProduct. As it stands, your save product flushes the entity manager so you end up saving/updating any entities (not just the specific product) that might have changed since all repositories share the same manager.

This has not been a problem for me. Just something to be aware of. If your modifying multiple products within a single request then you might want to break apart your persist and flush. The way all of your changes will be added to the database in one shot.

class ProductRepository
{
    public function persist($product) { return $this->_em->persist($product); }
    public function flush($product) { return $this->_em->flush(); }

One more for reason for this approach is that it allows you to swap out the repository for testing. I have yaml based repositories which load some entities from a yaml file. The repositories expose simple find/findAll methods making it easy to write test functions. And who knows, someday you may decide to switch to something other than Doctrine 2.

I use a base repository class:

use Doctrine\ORM\EntityRepository as BaseRepository;

class EntityRepository extends BaseRepository
{
    // Create main entity
    public function createEntity($params = array())
    {
        $entityName = $this->getEntityName();
        return new $entityName($params);
    }
    // Allow null for id
    public function find($id)
    {
        return $id ? parent::find($id) : null;
    }
    /* ==========================================================
     * Persistence
     */
    public function persist($entity) { return $this->getEntityManager()->persist($entity); }
    public function refresh($entity) { return $this->getEntityManager()->refresh($entity); }
    public function detach ($entity) { return $this->getEntityManager()->detach ($entity); }
    public function remove ($entity) { return $this->getEntityManager()->remove ($entity); }
    public function flush()          { return $this->getEntityManager()->flush();          }
    public function clear()          { return $this->getEntityManager()->clear();          

    public function getReference($id) { return $this->getEntityManager()->getReference($this->getEntityName(),$id); }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM