这是在 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 :
class ProductRepository extends EntityRepository
{
public function saveProduct( $p)
{
$this->_em->persist($p);
$this->_em->flush();
}
}
这是我的服务 Class :
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 - 这是进行依赖注入的好方法吗???
您需要这两行,因为存储库不扩展实体管理器。所以基本上你将 persist/flush 传递给实体管理器。这避免了将实体管理器暴露给您的服务的需要。您可以注入管理器并直接调用 persist/flush 但真的为什么要这么麻烦。
我一直在用你的方法。所以一定很棒。到目前为止,我还没有遇到任何严重的问题。
您应该知道调用 saveProduct 的副作用。就目前而言,您的保存产品会刷新实体管理器,因此您最终 saving/updating 任何可能已更改的实体(不仅仅是特定产品),因为所有存储库共享同一个管理器。
这对我来说不是问题。只是需要注意的事情。如果您在单个请求中修改多个产品,那么您可能希望拆分持久化和刷新。一次性将所有更改添加到数据库的方式。
class ProductRepository
{
public function persist($product) { return $this->_em->persist($product); }
public function flush($product) { return $this->_em->flush(); }
这种方法的另一个原因是它允许您换出存储库以进行测试。我有基于 yaml 的存储库,它从 yaml 文件加载一些实体。存储库公开了简单的 find/findAll 方法,使编写测试函数变得容易。谁知道呢,有一天你可能会决定转向 Doctrine 2 以外的东西。
我使用基本存储库 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); }
我这样注册了我的 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 :
class ProductRepository extends EntityRepository
{
public function saveProduct( $p)
{
$this->_em->persist($p);
$this->_em->flush();
}
}
这是我的服务 Class :
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 - 这是进行依赖注入的好方法吗???
您需要这两行,因为存储库不扩展实体管理器。所以基本上你将 persist/flush 传递给实体管理器。这避免了将实体管理器暴露给您的服务的需要。您可以注入管理器并直接调用 persist/flush 但真的为什么要这么麻烦。
我一直在用你的方法。所以一定很棒。到目前为止,我还没有遇到任何严重的问题。
您应该知道调用 saveProduct 的副作用。就目前而言,您的保存产品会刷新实体管理器,因此您最终 saving/updating 任何可能已更改的实体(不仅仅是特定产品),因为所有存储库共享同一个管理器。
这对我来说不是问题。只是需要注意的事情。如果您在单个请求中修改多个产品,那么您可能希望拆分持久化和刷新。一次性将所有更改添加到数据库的方式。
class ProductRepository
{
public function persist($product) { return $this->_em->persist($product); }
public function flush($product) { return $this->_em->flush(); }
这种方法的另一个原因是它允许您换出存储库以进行测试。我有基于 yaml 的存储库,它从 yaml 文件加载一些实体。存储库公开了简单的 find/findAll 方法,使编写测试函数变得容易。谁知道呢,有一天你可能会决定转向 Doctrine 2 以外的东西。
我使用基本存储库 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); }