这是在Symfony2中进行依赖项注入的好方法吗


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

我注册了我的services.yml文件,如下所示:

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]

这是我的存储库类:

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

这是我的服务类别:

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

这就是我在控制器中调用服务的方式:

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

所有的工作。我的问题是:1-你能向我解释为什么我需要这两行吗?即使我在EntityRepository中有EntityManager(由$this->_em使用)???

factory_service: doctrine.orm.default_entity_manager
factory_method: getRepository

2-这是进行依赖项注入的好方法吗???

  1. 您需要这两行,因为存储库不扩展实体管理器。因此,基本上您将persistent/flush传递给实体管理器。这就避免了向您的服务公开实体管理器的需要。您可以注入管理器并直接调用persistent/flush,但这真的很麻烦。

  2. 我一直用你的方法。所以它一定很棒。到目前为止,我还没有遇到任何严重的问题。

您应该意识到调用saveProduct的副作用。目前,您的存储产品会刷新实体管理器,因此您最终会保存/更新由于所有存储库共享同一管理器而可能发生更改的任何实体(而不仅仅是特定产品)。

这对我来说不是问题。只是需要注意的一点。如果您在一个请求中修改多个产品,那么您可能需要拆分持久化和刷新。您的所有更改将一次性添加到数据库的方式。

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

这种方法的另一个原因是,它允许您交换存储库进行测试。我有基于yaml的存储库,它们从yaml文件加载一些实体。存储库公开了简单的find/findAll方法,使编写测试函数变得容易。谁知道呢,有一天你可能会决定转向第二条原则之外的其他东西。

我使用一个基本存储库类:

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); }