我有类ModelsRepository:
class ModelsRepository extends EntityRepository
{}
服务
container_data:
class: ProjectName\MyBundle\Common\Container
arguments: [@service_container]
我希望从ModelsRepository访问service_data。我无法从控制器使用的构造函数传输服务。
你知道怎么做吗?
答案 0 :(得分:12)
恕我直言,不应该这样做,因为你可能很容易违反SRP和Law of Demeter等规则
但如果你真的需要它,这是一种方法:
首先,我们定义一个基础“ContainerAwareRepository”类,它有一个调用“setContainer”
的 services.yml 强>
services:
# This is the base class for any repository which need to access container
acme_bundle.repository.container_aware:
class: AcmeBundle\Repository\ContainerAwareRepository
abstract: true
calls:
- [ setContainer, [ @service_container ] ]
ContainerAwareRepository可能看起来像这样
的 AcmeBundle \库\ ContainerAwareRepository.php 强>
abstract class ContainerAwareRepository extends EntityRepository
{
protected $container;
public function setContainer(ContainerInterface $container)
{
$this->container = $container;
}
}
然后,我们可以定义我们的模型库
我们在这里使用了学说的getRepository
方法来构建我们的存储库
的 services.yml 强>
services:
acme_bundle.models.repository:
class: AcmeBundle\Repository\ModelsRepository
factory_service: doctrine.orm.entity_manager
factory_method: getRepository
arguments:
- "AcmeBundle:Models"
parent:
acme_bundle.repository.container_aware
然后,只需定义类
的 AcmeBundle \库\ ModelsRepository.php 强>
class ModelsRepository extends ContainerAwareRepository
{
public function findFoo()
{
$this->container->get('fooservice');
}
}
为了使用存储库,您绝对需要首先从服务中调用它。
$container->get('acme_bundle.models.repository')->findFoo(); // No errors
$em->getRepository('AcmeBundle:Models')->findFoo(); // No errors
但如果你直接做
$em->getRepository('AcmeBundle:Models')->findFoo(); // Fatal error, container is undefined
答案 1 :(得分:8)
你应该从不将容器传递给存储库,就像你永远不应该让实体处理繁重的逻辑一样。存储库只有一个目的 - 从数据库中检索数据。没有更多(阅读:http://docs.doctrine-project.org/en/2.0.x/reference/working-with-objects.html)。
如果你需要比这更复杂的东西,你应该为它创建一个单独的(容器意识到你想要的)服务。
答案 2 :(得分:6)
我尝试了一些版本。问题解决了
ModelRepository:
class ModelRepository extends EntityRepository
{
private $container;
function __construct($container, $em) {
$class = new ClassMetadata('ProjectName\MyBundle\Entity\ModelEntity');
$this->container = $container;
parent::__construct($em, $class);
}
}
security.yml:
providers:
default:
id: model_auth
services.yml
model_auth:
class: ProjectName\MyBundle\Repository\ModelRepository
argument
结果我得到了能力使用容器的存储库 - 根据需要。 但是这种实现只能在关键情况下使用,因为她对Repository有限制。 Thx 4all。
答案 3 :(得分:4)
您确定从repo访问服务是个好主意吗?
存储库是为自定义SQL而设计的,在学说的情况下,学说可以帮助您使用find()
,findOne()
,findBy()
,“魔术”方法。
考虑在您使用回购的地方注入您的服务,如果您需要一些参数,请将其直接传递给repo的方法。
答案 4 :(得分:4)
我建议使用工厂服务:
http://symfony.com/doc/current/components/dependency_injection/factories.html
//Repository
class ModelsRepositoryFactory
{
public static function getRepository($entityManager,$entityName,$fooservice)
{
$em = $entityManager;
$meta = $em->getClassMetadata($entityName);
$repository = new ModelsRepository($em, $meta, $fooservice);
return $repository;
}
}
//service
AcmeBundle.ModelsRepository:
class: Doctrine\ORM\EntityRepository
factory: [AcmeBundle\Repositories\ModelsRepositoryFactory,getRepository]
arguments:
- @doctrine.orm.entity_manager
- AcmeBundle\Entity\Models
- @fooservice
答案 5 :(得分:3)
我非常同意只有在绝对必要时才能这样做。虽然现在有一种非常简单的方法(用Symfony 2.8测试)。
RepositoryClass:
namespace AcmeBundle\Repository;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
use AcmeBundle\Entity\User;
class UserRepository extends EntityRepository implements ContainerAwareInterface
{
use ContainerAwareTrait;
public function findUserBySomething($param)
{
$service = $this->container->get('my.other.service');
}
}
services.yml:
acme_bundle.repository.user:
lazy: true
class: AcmeBundle\Repository\UserRepository
factory: ['@doctrine.orm.entity_manager', getRepository]
arguments:
- "AcmeBundle:Entity/User"
calls:
- method: setContainer
arguments:
- '@service_container'
答案 6 :(得分:1)
扩展LaurynasMališauskas的答案,将服务传递给构造函数,使您的存储库也成为服务并使用参数传递它:
models.repository:
class: ModelsRepository
arguments: ['@service_you_want_to_pass']
答案 7 :(得分:0)
最简单的方法是将服务注入存储库构造函数。
class ModelsRepository extends EntityRepository
{
private $your_service;
public function __construct(ProjectName\MyBundle\Common\Container $service) {
$this->your_service = $service;
}
}