php Symfony2:如何从存储库访问服务
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12971552/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Symfony2: How to access to service from repository
提问by Alastor
I have class ModelsRepository:
我有类 ModelsRepository:
class ModelsRepository extends EntityRepository
{}
And service
和服务
container_data:
class: ProjectName\MyBundle\Common\Container
arguments: [@service_container]
I want get access from ModelsRepository to service container_data. I can't transmit service from controller used constructor.
我想从 ModelsRepository 访问服务 container_data。我无法从控制器使用的构造函数传输服务。
Do you know how to do it?
你知道怎么做吗?
采纳答案by Alastor
I tried some versions. Problem was solved follows
我尝试了一些版本。问题解决如下
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:
安全.yml:
providers:
default:
id: model_auth
services.yml
服务.yml
model_auth:
class: ProjectName\MyBundle\Repository\ModelRepository
argument
As a result I got repository with ability use container - as required. But this realization can be used only in critical cases, because she has limitations for Repository. Thx 4all.
结果,我根据需要获得了具有使用容器能力的存储库。但是这种实现只能在危急情况下使用,因为她对 Repository 有限制。谢谢 4all。
回答by Touki
IMHO, this shouldn't be needed since you may easily break rules like SRPand Law of Demeter
恕我直言,这不应该是必需的,因为您可能很容易违反SRP和Demeter法则之类的规则
But if you really need it, here's a way to do this:
但如果你真的需要它,这里有一种方法可以做到这一点:
First, we define a base "ContainerAwareRepository" class which has a call "setContainer"
首先,我们定义一个基本的“ContainerAwareRepository”类,它有一个调用“setContainer”
services.yml
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 ]?]
The ContainerAwareRepository may looks like this
ContainerAwareRepository 可能如下所示
AcmeBundle\Repository\ContainerAwareRepository.php
AcmeBundle\Repository\ContainerAwareRepository.php
abstract class ContainerAwareRepository extends EntityRepository
{
protected $container;
public function setContainer(ContainerInterface $container)
{
$this->container = $container;
}
}
Then, we can define our Model Repository.
We use here, the doctrine's getRepositorymethod in order to construct our repository
然后,我们可以定义我们的模型存储库。
我们在这里使用学说的getRepository方法来构建我们的存储库
services.yml
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
And then, just define the class
然后,只需定义类
AcmeBundle\Repository\ModelsRepository.php
AcmeBundle\Repository\ModelsRepository.php
class ModelsRepository extends ContainerAwareRepository
{
public function findFoo()
{
$this->container->get('fooservice');
}
}
In order to use the repository, you absolutely need to call it from the service first.
为了使用存储库,您绝对需要先从服务中调用它。
$container->get('acme_bundle.models.repository')->findFoo(); // No errors
$em->getRepository('AcmeBundle:Models')->findFoo(); // No errors
But if you directly do
但是如果你直接做
$em->getRepository('AcmeBundle:Models')->findFoo(); // Fatal error, container is undefined
回答by Itako
You should neverpass container to the repository, just as you should never let entities handle heavy logic. Repositories have only one purpose - retrieving data from the database. Nothing more (read: http://docs.doctrine-project.org/en/2.0.x/reference/working-with-objects.html).
你永远不应该将容器传递给存储库,就像你永远不应该让实体处理繁重的逻辑一样。存储库只有一个目的——从数据库中检索数据。仅此而已(阅读:http: //docs.doctrine-project.org/en/2.0.x/reference/working-with-objects.html)。
If you need anything more complex than that, you should probably create a separate (container aware if you wish) service for that.
如果您需要比这更复杂的任何东西,您可能应该为此创建一个单独的(容器感知,如果您愿意)服务。
回答by Piers
I would suggest using a factory service:
我建议使用工厂服务:
http://symfony.com/doc/current/components/dependency_injection/factories.html
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
回答by DonCallisto
Are you sure that is a good idea to access service from repo?
您确定从 repo 访问服务是个好主意吗?
Repositories are designed for custom SQL where, in case of doctrine, doctrine can help you with find(),findOne(),findBy(), [...] "magic" methods.
存储库是为自定义 SQL 设计的,在这种情况下,学说可以帮助您使用find(), findOne(), findBy(), [...] “魔术”方法。
Take into account to inject your service where you use your repo and, if you need some parameters, pass it directly to repo's method.
考虑在您使用 repo 的地方注入您的服务,如果您需要一些参数,请将其直接传递给 repo 的方法。
回答by con
I strongly agree that this should only be done when absolutely necessary. Though there is a quite simpler approach possible now (tested with Symfony 2.8).
我强烈同意只有在绝对必要时才应该这样做。尽管现在可能有一种非常简单的方法(使用 Symfony 2.8 进行测试)。
- Implement in your repository "ContainerAwareInterface"
- Use the "ContainerAwareTrait"
- adjust the services.yml
- 在您的存储库中实现“ContainerAwareInterface”
- 使用“ContainerAwareTrait”
- 调整 services.yml
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:
服务.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'
回答by Laurynas Mali?auskas
the easiest way is to inject the service into repository constructor.
最简单的方法是将服务注入存储库构造函数。
class ModelsRepository extends EntityRepository
{
private $your_service;
public function __construct(ProjectName\MyBundle\Common\Container $service) {
$this->your_service = $service;
}
}
回答by S3Mi
Extending Laurynas Mali?auskas answer, to pass service to a constructor make your repository a service too and pass it with arguments:
扩展 Laurynas Mali?auskas 答案,将服务传递给构造函数使您的存储库也成为服务并通过参数传递它:
models.repository:
class: ModelsRepository
arguments: ['@service_you_want_to_pass']

