I have class ModelsRepository:
class ModelsRepository extends EntityRepository
{}
And service
container_data:
class:
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.
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.
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
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;
}
}
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']
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