Sylius: How to inject (request) arguments in custom ProductRepository? - php

I want to override the method createByTaxonPaginator() so that the indexByTaxon() method gives back sorted results. That new method should use Request to get the sort Get-Parameter.
For ordering the searchresults i found the service and overrode that as following:
sylius_search.repository:
class: ShopBundle\Entity\SearchIndexRepository
arguments: ['#doctrine.orm.entity_manager', '#sylius.repository.product', '#request_stack']
maybe that is not a good practice, i dont know. But it works...
unfortunately i didnt find any service definition for sylius.repository.product to have a look on the required args.
in my config i have following:
sylius_product:
classes:
product:
model: ShopBundle\Entity\Product # My Own Entity
controller: Sylius\Bundle\CoreBundle\Controller\ProductController
repository: ShopBundle\Entity\ProductRepository
# is there an option for injecting arguments?
form:
default: ShopBundle\Form\Type\ProductType
translation:
model: ShopBundle\Entity\ProductTranslation
form:
default: ShopBundle\Form\Type\ProductTranslationType
is there an option for injecting args which i didn't know? Here the Repo which extends the default one and overloads the Method createByTaxonPaginator()
<?php
namespace ShopBundle\Entity;
use Sylius\Bundle\CoreBundle\Doctrine\ORM\ProductRepository as BaseProductRepository;
use Sylius\Component\Core\Model\TaxonInterface;
class ProductRepository extends BaseProductRepository
{
/**
* Create paginator for products categorized under given taxon.
* Modified: Sorting of Taxon listing added
*
* #param TaxonInterface $taxon
* #param array $criteria
*
* #return \Pagerfanta\Pagerfanta
*/
public function createByTaxonPaginator(TaxonInterface $taxon, array $criteria = array())
{
// Here i want to have the Request $request arg..
$queryBuilder = $this->getCollectionQueryBuilder();
$queryBuilder
->innerJoin('product.taxons', 'taxon')
->andWhere($queryBuilder->expr()->orX(
'taxon = :taxon',
':left < taxon.left AND taxon.right < :right'
))
->setParameter('taxon', $taxon)
->setParameter('left', $taxon->getLeft())
->setParameter('right', $taxon->getRight())
->orderBy('translation.name') // ... to get this dynamic
;
$this->applyCriteria($queryBuilder, $criteria);
return $this->getPaginator($queryBuilder);
}
}

I'm not sure I completely understand the question but here is an example of defining a repository service and then injecting an additional service. You cannot use constructor injection for the request stack because the repository itself is created using the entity manager as a factory:
sylius.repository.product:
class: ShopBundle\Entity\ProductRepository
factory: ['#doctrine.orm.entity_manager', 'getRepository']
arguments:
- 'ShopBundle\Entity\Product'
calls: [[setRequestStack, ['#request_stack']]]
You will need to add setRequestStack to your custom repository.
You might also want to rethink the whole notion of making these services depend on the request object. Tends to get messy. Might be better to pass the sort parameter as an argument in your methods calls.
Update 13 Sep 2019:
This answer is obsolete. In most cases you will want to derive your repository from the ServiceEntityRepository and then inject the RequestStack into the constructor. This answer is still valid for 2.x.

Related

Symfony - inject doctrine repository in service

according to How to inject a repository into a service in Symfony2?
it's like
acme.custom_repository:
class: Doctrine\ORM\EntityRepository
factory: ['#doctrine.orm.entity_manager', getRepository]
arguments:
- 'Acme\FileBundle\Model\File'
but I get an Exception
Invalid service "acme.custom_repository": class
"EntityManager5aa02de170f88_546a8d27f194334ee012bfe64f629947b07e4919__CG__\Doctrine\ORM\EntityManager"
does not exist.
How can I do this in Symfony 3.4?
update:
EntityClass is actually a valid class FQCN (also used copy reference on phpstorm to be sure) , just renamed it because a companies name is in it :). updated it anyway.
solution
BlueM's solution works perfectly.
In case you are not using autowiring here's the service defintion:
Acme\AcmeBundle\Respository\MyEntityRepository:
arguments:
- '#Doctrine\Common\Persistence\ManagerRegistry'
- Acme\AcmeBundle\Model\MyEntity # '%my_entity_class_parameter%'
As you are using Symfony 3.4, you can use a much simpler approach, using ServiceEntityRepository. Simply implement your repository, let it extend class ServiceEntityRepository and you can simply inject it. (At least when using autowiring – I haven’t used this with classic DI configuration, but would assume it should also work.)
In other words:
namespace App\Repository;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
class ExampleRepository extends ServiceEntityRepository
{
/**
* #param ManagerRegistry $managerRegistry
*/
public function __construct(ManagerRegistry $managerRegistry)
{
parent::__construct($managerRegistry, YourEntity::class);
}
}
Now, without any DI configuration, you can inject the repository wherever you want, including controller methods.
One caveat (which equally applies to the way you try to inject the repository): if the Doctrine connection is reset, you will have a reference to a stale repository. But IMHO, this is a risk I accept, as otherwise I won’t be able to inject the repository directly..
Create the custom repository properly
First, you need to create the repository custom class that extends the default repository from doctrine:
use Doctrine\ORM\EntityRepository;
class UserRepository extends EntityRepository
{
// your own methods
}
Then you need this annotation in the entity class:
/**
* #ORM\Entity(repositoryClass="MyDomain\Model\UserRepository")
*/
Then you define the repository in the .yml file:
custom_repository:
class: MyDomain\Model\UserRepository
factory: ["#doctrine", getRepository]
arguments:
- Acme\FileBundle\Model\File
Make sure that in the definition of your repository class points to your custom repository class and not to Doctrine\ORM\EntityRepository.
Inject custom services into your custom repository:
On your custom repository create custom setters for your services
use Doctrine\ORM\EntityRepository;
class UserRepository extends EntityRepository
{
protected $paginator;
public function setPaginator(PaginatorInterface $paginator)
{
$this->paginator = $paginator;
}
}
Then inject them like this:
custom_repository:
class: MyDomain\Model\UserRepository
factory: ["#doctrine", getRepository]
arguments:
- Acme\FileBundle\Model\File
calls:
- [setPaginator, ['#knp_paginator']]
Inject your repository into a service:
my_custom_service:
class: Acme\FileBundle\Services\CustomService
arguments:
- "#custom_repository"
Check the arguments is a valid class (with FQCN or with a bundle simplification) as example:
acme.custom_repository:
class: Doctrine\ORM\EntityRepository
factory:
- '#doctrine.orm.entity_manager'
- getRepository
arguments:
- Acme\MainBundle\Entity\MyEntity
or
acme.custom_repository:
class: Doctrine\ORM\EntityRepository
factory:
- '#doctrine.orm.entity_manager'
- getRepository
arguments:
- AcmeMainBundle:MyEntity
Hope this help
Solutions I could see here so far are not bad. I looked at it from a different angle. So my solution allows you to keep clean repositories, sorta enforces consistent project structure and you get to keep autowiring!
This is how I would solve it in Symfony 5.
GOAL
We want to have autowired Repositories and we want to keep them as clean as possible. We also want them to be super easy to use.
PROBLEM
We need to figure out a way to tell Repository about the entity it should use.
SOLUTION
The solution is simple and consists of a few things:
We have custom Repository class which extends Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository class.
Our custom class has public string $entity property on it.
When we create our new repository and extend our custom repository class we have two choices: on our new repository we can just point to the class like this
namespace App\Database\Repository\Post;
use App\Database\Repository\Repository;
use App\Entity\Blog\Post;
/**
* Class PostRepository
* #package App\Database\Repository
*/
class PostRepository extends Repository
{
public string $entity = Post::class;
public function test()
{
dd(99999, $this->getEntityName());
}
}
or we could omit that property and let our new base Repository class find it automatically! (More about that later.)
CODE
So let's start with the code and then I will explain it:
<?php
namespace App\Database\Repository;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Laminas\Code\Reflection\ClassReflection;
use Symfony\Component\Finder\Finder;
/**
* Class Repository
* #package App\Database\Repository
*/
abstract class Repository extends ServiceEntityRepository
{
/** #var string */
private const REPOSITORY_FILE = 'repository';
/** #var string */
public string $entity = '';
/** #var string */
public string $defaultEntitiesLocation;
/** #var string */
public string $defaultEntitiesNamespace;
/**
* Repository constructor.
*
* #param ManagerRegistry $registry
* #param $defaultEntitiesLocation
* #param $defaultEntitiesNamespace
* #throws \Exception
*/
public function __construct(
ManagerRegistry $registry,
$defaultEntitiesLocation,
$defaultEntitiesNamespace
) {
$this->defaultEntitiesLocation = $defaultEntitiesLocation;
$this->defaultEntitiesNamespace = $defaultEntitiesNamespace;
$this->findEntities();
parent::__construct($registry, $this->entity);
}
/**
* Find entities.
*
* #return bool
* #throws \ReflectionException
*/
public function findEntities()
{
if (class_exists($this->entity)) {
return true;
}
$repositoryReflection = (new ClassReflection($this));
$repositoryName = strtolower(preg_replace('/Repository/', '', $repositoryReflection->getShortName()));
$finder = new Finder();
if ($finder->files()->in($this->defaultEntitiesLocation)->hasResults()) {
foreach ($finder as $file) {
if (strtolower($file->getFilenameWithoutExtension()) === $repositoryName) {
if (!empty($this->entity)) {
throw new \Exception('Entity can\'t be matched automatically. It looks like there is' .
' more than one ' . $file->getFilenameWithoutExtension() . ' entity. Please use $entity
property on your repository to provide entity you want to use.');
}
$namespacePart = preg_replace(
'#' . $this->defaultEntitiesLocation . '#',
'',
$file->getPath() . '/' . $file->getFilenameWithoutExtension()
);
$this->entity = $this->defaultEntitiesNamespace . preg_replace('#/#', '\\', $namespacePart);
}
}
}
}
}
Ok, so what is happening here? I have bound some values to the container in services.yml:
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
bind:
$defaultEntitiesLocation: '%kernel.project_dir%/src/Entity'
$defaultEntitiesNamespace: 'App\Entity'
Then in our new extension class, I know where by default to look for my Entities (this enforces some consistency).
VERY IMPORTANT BIT - I assume that we will name Repositories and Entities with exactly the same so for example: Post will be our Entity and PostRepository is our repository. Just note that the word Repository is not obligatory. If it is there it will be removed.
Some clever logic will create namespaces for you - I assume that you will follow some good practices and that it will all be consistent.
It's done! To have your repository autowired all you need to do is extend your new base repository class and name Entity the same as the repository. so End result looks like this:
<?php
namespace App\Database\Repository\Post;
use App\Database\Repository\Repository;
use App\Entity\Blog\Post;
/**
* Class PostRepository
* #package App\Database\Repository
*/
class PostRepository extends Repository
{
public function test()
{
dd(99999, $this->getEntityName());
}
}
It is CLEAN, AUTOWIRED, SUPER EASY AND QUICK TO CREATE!
What about the drawbacks about the ServiceEntityRepository?
https://symfony.com/doc/current/doctrine/multiple_entity_managers.html
One entity can be managed by more than one entity manager. This
however results in unexpected behavior when extending from
ServiceEntityRepository in your custom repository. The
ServiceEntityRepository always uses the configured entity manager for
that entity.
In order to fix this situation, extend EntityRepository instead and no
longer rely on autowiring:
In an own project I've seen that using:
$repository = $entityManager->getRepository(MyEntity:class)
The $repository->_em is not equals to $entityManager (with both using the same connection), causing problems like:
$entity = $entityManager->getRepository(MyEntity:class)->find($id);
$entityManager->refresh($entity); // throws 'entity is not managed'
That's why the entity is fetched with $repository->_em and the refresh (or persist, flush, etc.) is using $entityManager.
This problem is described here:
https://github.com/symfony/symfony-docs/issues/9878
So... You can't rely in ServiceEntityRepository using multiple entity managers, but the EntityRepository doesn't allow autowire, so, what?
My two cents (I believe this should be works in every scenario):
Manually set the class metadata (something like you need to do in the constructor of the ServiceEntityManager), so I can:
Remove the autowire of repositories in services.yaml:
App\:
resource: '../src/*'
exclude: '../src/{Entity,Migrations,Repository,Tests,Kernel.php,Client}'
(you also add the repositories below in services.yaml)
And create another /config/packages/repositories.yaml and add:
my.entity.metadata:
class: App\Entity\Metadata
arguments:
$entityName: App\Entity\MyEntity
App\Repository\MyEntityRepository:
arguments:
[$class: my.entity.metadata]
Now you have a EntityRepository that is capable of being autowireable. You can make a repositories.yaml file in the config and keep updated when you create/edit/delete your repositories. Is not cleanest but it should be works.

Organize the models in Symfony 3

I just read the official Symfony 3 docs and point when I need to retrieve objects from database I should use something like this:
$repository = $em->getRepository('AppBundle:Product');
Here Product is just an entity class with no parent, so Doctrine work with it through annotations. But I'm not sure it's a good idea to hardcode the model name in quotes. What if later I conclude to name the model Good, should I search through the whole project and replace Product on Good. I Laravel for example, each model extends the base model class so I could write : Product::model()->find('nevermind') . Is there any such option in Symfony 3.3?
I'm not shure if it is a solution for your problem, but you can write:
$repository = $em->getRepository(Product::class);
The $em->getRepository('...') returns a mixed datatype (depends on the first parameter). Even you write $repository = $em->getRepository(Product::class); the IDE cannot resolve the real datatype. I suggest this method (pseudo code):
/**
* Get product repo
*
* #return ProductRepository
*/
public function getProductRepository()
{
return $this->getEntityManager()->getRepository(Product::class);
}
/**
* #return \Doctrine\ORM\EntityManager
*/
public function getEntityManager(): EntityManager
{
return $this->getDoctrine()->getManager();
}
You can declare the repository as a service like this:
services:
app.product_repo:
class: AppBundle\Entity\ProductRepository
factory: ['#doctrine.orm.default_entity_manager', getRepository]
arguments:
- AppBundle\Entity\Product
Then in your controller:
$repository = $em->get('app.product_repo');
Well at least it works with PHPStorm and its Symfony plugin. Having auto-complete for services is really a must.

Is it considered a bad practice to add fields to Symfony entity in controller?

Is it considered a bad practice to add fields to Symfony entity in controller? For example lets say that I have a simple entity:
/**
* #ORM\Entity
* #ORM\Table(name="user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
public function __construct()
{
parent::__construct();
}
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
}
}
And then in UserController.php I want to do the following:
foreach($users as $user){
$user->postsCount = someMethodThatWillCountPosts();
}
So later that postsCount can be displayed in Twig. Is it a bad practice?
Edit:
It's important to count posts on side of mysql database, there will be more than 50.000 elements to count for each user.
Edit2:
Please take a note that this questions is not about some particular problem but rather about good and bad practices in object oriented programming in Symfony.
As #Rooneyl explained that if you have relation between user and post then you can get count easily in your controller, refer this for the same. But if you are looking to constructing and using more complex queries from inside a controller. In order to isolate, reuse and test these queries, it's a good practice to create a custom repository class for your entity.Methods containing your query logic can then be stored in this class.
To do this, add the repository class name to your entity's mapping definition:
// src/AppBundle/Entity/Product.php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="AppBundle\Repository\ProductRepository")
*/
class Product
{
//...
}
Doctrine can generate empty repository classes for all the entities in your application via the same command used earlier to generate the missing getter and setter methods:
$ php bin/console doctrine:generate:entities AppBundle
If you opt to create the repository classes yourself, they must extend
Doctrine\ORM\EntityRepository.
More Deatils
Updated Answer
In many cases associations between entities can get pretty large. Even in a simple scenario like a blog. where posts can be commented, you always have to assume that a post draws hundreds of comments. In Doctrine 2.0 if you accessed an association it would always get loaded completely into memory. This can lead to pretty serious performance problems, if your associations contain several hundreds or thousands of entities.
With Doctrine 2.1 a feature called Extra Lazy is introduced for associations. Associations are marked as Lazy by default, which means the whole collection object for an association is populated the first time its accessed. If you mark an association as extra lazy the following methods on collections can be called without triggering a full load of the collection: SOURCE
"rather about good and bad practices in object oriented programming"
If that's the case then you really shouldn't have any business logic in controller, you should move this to services.
So if you need to do something with entities before passing them to twig template you might want to do that in specific service or have a custom repository class that does that (maybe using some other service class) before returning the results.
i.e. then your controller's action could look more like that:
public function someAction()
{
//using custom repository
$users = $this->usersRepo->getWithPostCount()
//or using some other service
//$users = $this->usersFormatter->getWithPostCount(x)
return $this->render('SomeBundle:Default:index.html.twig', [
users => $users
]);
}
It's really up to you how you're going to do it, the main point to take here is that best practices rather discourage from having any biz logic in controller. Just imagine you'll need to do the same thing in another controller, or yet some other service. If you don't encapsulate it in it's own service then you'll need to write it every single time.
btw. have a read there:
http://symfony.com/doc/current/best_practices/index.html

How to get the instance of Kernel in the Entity class in Symfony2

The title explains the question pretty well. I am in the lifecycle callback of the Doctrine Entity class and want to do some extra DB entries. For this I need to get an instance of the Kernel. How can I do this?
Needing the container/kernel in an entity is most of the time, wrong. An entity shouldn't be aware of any services. Why is that?
Basically, an entity is an object which represents a thing. An entity is mostly used in a relationnal database, but you can at any time use this entity for other matters (serialize it, instanciate it from an HTTP layer...).
You want your entity to be unit-testable, this means you need to be able to instanciate your entity easily, without anything around, mostly, without any piece of business logic.
You should move your logic into another layer, the one that will instanciate your entity.
For your use case, I think, the most easy way is to use a doctrine event.
services.yml
services:
acme_foo.bar_listener:
class: Acme\FooBundle\Bar\BarListener
arguments:
- #kernel
tags:
- { name: doctrine.event_listener, event: postLoad }
Acme\FooBundle\Bar\BarListener
use Symfony\Component\HttpKernel\KernelInterface;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Acme\FooBundle\Entity\Bar;
class BarListener
{
protected $kernel;
/**
* Constructor
*
* #param KernelInterface $kernel A kernel instance
*/
public function __construct(KernelInterface $kernel)
{
$this->kernel = $kernel;
}
/**
* On Post Load
* This method will be trigerred once an entity gets loaded
*
* #param LifecycleEventArgs $args Doctrine event
*/
public function postLoad(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if (!($entity instanceof Bar)) {
return;
}
$entity->setEnvironment($this->kernel->getEnvironment());
}
}
And there you go, your entity remains flat without dependencies, and you can easily unit test your event listener
if you have to use some service, you shouldn't use whole container or kernel instance especially.
use the services itself - always try to inject single service, not whole container
your case looks like you should use doctrine events

Symfony2: How to inject ALL parameters in a service?

How can I inject ALL parameters in a service?
I know I can do: arguments: [%some.key%] which will pass the parameters: some.key: "value" to the service __construct.
My question is, how to inject everything that is under parameters in the service?
I need this in order to make a navigation manager service, where different menus / navigations / breadcrumbs are to be generated according to different settings through all of the configuration entries.
I know I could inject as many parameters as I want, but since it is going to use a number of them and is going to expand as time goes, I think its better to pass the whole thing right in the beginning.
Other approach might be if I could get the parameters inside the service as you can do in a controller $this -> container -> getParameter('some.key');, but I think this would be against the idea of Dependency Injection?
Thanks in advance!
It is not a good practice to inject the entire Container into a service. Also if you have many parameters that you need for your service it is not nice to inject all of them one by one to your service. Instead I use this method:
1) In config.yml I define the parameters that I need for my service like this:
parameters:
product.shoppingServiceParams:
parameter1: 'Some data'
parameter2: 'some data'
parameter3: 'some data'
parameter4: 'some data'
parameter5: 'some data'
parameter6: 'some data'
2) Then I inject this root parameter to my service like:
services:
product.shoppingService:
class: Saman\ProductBundle\Service\Shopping
arguments: [#translator.default, %product.shoppingServiceParams%]
3) In may service I can access these parameters like:
namespace Saman\ProductBundle\Service;
use Symfony\Bundle\FrameworkBundle\Translation\Translator;
class Shopping
{
protected $translator;
protected $parameters;
public function __construct(
Translator $translator,
$parameters
)
{
$this->translator = $translator;
$this->parameters = $parameters;
}
public function dummyFunction()
{
var_dump($this->getParameter('parameter2'));
}
private function getParameter($key, $default = null)
{
if (isset($this->parameters[$key])) {
return $this->parameters[$key];
}
return $default;
}
}
4) I can also set different values for different environments. For example in config_dev.yml
parameters:
product.shoppingServiceParams:
parameter1: 'Some data for dev'
parameter2: 'some data for dev'
parameter3: 'some data for dev'
parameter4: 'some data for dev'
parameter5: 'some data for dev'
parameter6: 'some data'
Another variant how to get parameters easy - you can just set ParameterBag to your service. You can do it in different ways - via arguments or via set methods. Let me show my example with set method.
So in services.yml you should add something like:
my_service:
class: MyService\Class
calls:
- [setParameterBag, ["#=service('kernel').getContainer().getParameterBag()"]]
and in class MyService\Class just add use:
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
and create 2 methods:
/**
* Set ParameterBag for repository
*
* #param ParameterBagInterface $params
*/
public function setParameterBag(ParameterBagInterface $params)
{
$this->parameterBag = $params;
}
/**
* Get parameter from ParameterBag
*
* #param string $name
* #return mixed
*/
public function getParameter($name)
{
return $this->parameterBag->get($name);
}
and now you can use in class:
$this->getParameter('your_parameter_name');
I believe you're supposed to pass the parameters individually. I think it's made that way by design so your service class is not dependent on the AppKernel. That way you can reuse your service class outside your Symfony project. Something that is useful when testing your service class.
Note: I know that this solution is not BEST from design point of view, but it does the job, so please avoid down-voting.
You can inject \AppKernel object and then access all parameters like this:
config.yml:
my_service:
class: MyService\Class
arguments: [#kernel]
And inside MyService\Class:
public function __construct($kernel)
{
$this->parameter = $kernel->getContainer()->getParameter('some.key');
// or to get all:
$this->parameters = $kernel->getContainer()->getParameterBag()->all();
}
AppKernel would work but it's even worse (from a scope perspective) than injecting the container since the kernel has even more stuff in it.
You can look at xxxProjectContainer in your cache directory. Turns out that the assorted parameters are compiled directly into it as a big array. So you could inject the container and then just pull out the parameters. Violates the letter of the law but not the spirit of the law.
class MyService {
public function __construct($container) {
$this->parameters = $container->parameters; // Then discard container to preclude temptation
And just sort of messing around I found I could do this:
$container = new \arbiterDevDebugProjectContainer();
echo 'Parameter Count ' . count($container->parameters) . "\n";
So you could actually create a service that had basically a empty copy of the master container and inject it just to get the parameters. Have to take into account the dev/debug flags which might be a pain.
I suspect you could also do it with a compiler pass but have never tried.
Suggestion to define a service at services.yml, which will inject the parameterBag and allow access to any of your parameter
service.container_parameters:
public: false
class: stdClass
factory_service: service_container
factory_method: getParameterBag
Inject your service, and u can get your parameter using below
$parameterService->get('some.key');
As alternative approach would be that you can actually inject application parameters into your service via Container->getParameterBag in you bundle DI Extension
<?php
namespace Vendor\ProjectBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
/**
* This is the class that loads and manages your bundle configuration
*
* To learn more see {#link http://symfony.com/doc/current/cookbook/bundles/extension.html}
*/
class VendorProjectExtension extends Extension {
/**
* {#inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container) {
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
$loader->load('services.yml');
/** set params for services */
$container->getDefinition('my.managed.service.one')
->addMethodCall('setContainerParams', array($container->getParameterBag()->all()));
$container->getDefinition('my.managed.service.etc')
->addMethodCall('setContainerParams', array($container->getParameterBag()->all()));
}
}
Please note that we can not inject ParameterBag object directly, cause it throws:
[Symfony\Component\DependencyInjection\Exception\RuntimeException]
Unable to dump a service container if a parameter is an object or a
resource.
Tested under Symfony version 2.3.4

Categories