I'm trying to dynamically set a parameter in Symfony2 (that I cannot statically set in my parameters.yml
file). My approach is to use an EventListener
:
namespace Acme\AcmeBundle\EventListener;
use Symfony\Component\DependencyInjection\Container;
class AcmeListener
{
private $container;
public function __construct(Container $container)
{
$this->container = $container;
}
public function onKernelRequest()
{
// Dynamically fetch $bar
$bar = fetch('foobar');
// Set parameter
$this->container->setParameter('foo', $bar);
}
}
And my service definition in config.yml
looks like this:
service:
kernel.listener.acme_listener:
class: Acme\AcmeBundle\EventListener\AcmeListener
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
arguments: [ '@service_container' ]
The problem is, I get an exception:
LogicException: Impossible to call set() on a frozen ParameterBag.
How can I work around this exception or do you see another way to dynamically set a parameter?
The container parameters rule is that:
You can only set a parameter before the container is compiled
How to remedy the problem depends on your needs with the premise that the container is not thought to have dynamic parameters.
create you custom dynamic "options" service and inject it in other services, in this way you can also manage your parameters in database (like wordpress wp_options), but i don't know a bundle that do this. For existing services (ex. mailer) you can use configurators.
invalidate the cache when parameters changes here an easy method so when you reload the page the container is rebuilt. If the parameters change frequently risks to reload the cache frequently and this becomes a problem if you have large loads.
if you choose the second option you need to set the parameters before it is filled in the container, so you can:
I suggest, however, option 1 (options service and configurators) because (I repeat) the container is not thought to have dynamic parameters but it offers the ability to have custom dynamic service configurators that use data from any source.
I had the problem on a list of URLs starting by %base_url%
when I wanted to do a failover system.
I finally replaced %base_url%
by #base_url#
and did a manual placeholders resolution in a service.
$tries = array (
$this->container->getParameter('base_url'),
$this->container->getParameter('base_url_failover'),
);
foreach ($tries as $try)
{
$url = str_replace('#base_url#', $try, $unresolvedUrl);
// whatever
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With