Symfony2: How to access to service from repository

后端 未结 8 1689
有刺的猬
有刺的猬 2020-12-31 13:08

I have class ModelsRepository:

class ModelsRepository extends EntityRepository
{}

And service

container_data:
 class:               


        
相关标签:
8条回答
  • 2020-12-31 13:41

    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:

    providers:
        default:
            id: model_auth
    

    services.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.

    0 讨论(0)
  • 2020-12-31 13:42

    You should never pass 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).

    If you need anything more complex than that, you should probably create a separate (container aware if you wish) service for that.

    0 讨论(0)
  • 2020-12-31 13:48

    I would suggest using a factory service:

    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  
    
    0 讨论(0)
  • 2020-12-31 13:51

    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;
      } 
    }
    
    0 讨论(0)
  • 2020-12-31 13:56

    Extending Laurynas Mališauskas answer, to pass service to a constructor make your repository a service too and pass it with arguments:

    models.repository:
          class: ModelsRepository
          arguments: ['@service_you_want_to_pass']
    
    0 讨论(0)
  • 2020-12-31 13:57

    IMHO, this shouldn't be needed since you may easily break rules like SRP and Law of 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"

    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

    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 getRepository method in order to construct our repository

    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

    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
    
    0 讨论(0)
提交回复
热议问题