Я зарегистрировал свой файл 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- Можете ли вы объяснить мне, почему мне нужны эти 2 строки, даже если у меня есть EntityManager в EntityRepository (используется $ this -> _ em) ???
factory_service: doctrine.orm.default_entity_manager
factory_method: getRepository
2 — это хороший способ сделать инъекцию зависимости ???
Вам нужны две строки, потому что хранилище не расширяет менеджер сущностей. Таким образом, в основном вы передаете persist / flush менеджеру сущностей. Это избавляет от необходимости выставлять менеджера сущностей для вашего сервиса. Вы могли бы ввести менеджера и позвонить по-прежнему / сбрасывать напрямую, но на самом деле зачем.
Я использую твой подход все время. Так что это должно быть здорово. На данный момент я не столкнулся с серьезными проблемами.
Вы должны знать о побочном эффекте вызова saveProduct. В существующем состоянии ваш продукт сохранения сбрасывает менеджер сущностей, поэтому вы в конечном итоге сохраняете / обновляете любые сущности (не только конкретный продукт), которые могли измениться, поскольку все репозитории имеют одного и того же менеджера.
Это не было проблемой для меня. Просто что-то, о чем нужно знать. Если вы изменяете несколько продуктов в рамках одного запроса, возможно, вы захотите разбить их на части. Способ, которым все ваши изменения будут добавлены в базу данных за один раз.
class ProductRepository
{
public function persist($product) { return $this->_em->persist($product); }
public function flush($product) { return $this->_em->flush(); }
Еще одна причина такого подхода заключается в том, что он позволяет заменить репозиторий для тестирования. У меня есть репозитории на основе yaml, которые загружают некоторые объекты из файла yaml. В репозиториях представлены простые методы find / findAll, облегчающие написание тестовых функций. И кто знает, когда-нибудь вы решите переключиться на что-то другое, кроме Доктрины 2.
Я использую базовый класс репозитория:
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); }
Других решений пока нет …