Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing the AppKernel environment variable in symfony 2

I'm Using symfony 2 and we have 2 configurations, dev and prod. I need to know if I can find out which one im using inside an Entity or Model.

I'm looking for something similar to this code found in AppKernel.php:

$this->getEnvironment()

If I could load the Kernel to call this that would be great but I can't find a way to do this. After looking into this it appears that symfony events may return the Kernel but I don't know how or where to capture these events so that I can call getKernel() on them. http://symfony.com/doc/current/book/internals.html

For example, they list this example:

use Symfony\Component\HttpKernel\Event\FilterControllerEvent;

public function onKernelController(FilterControllerEvent $event)
{
    $controller = $event->getController();
    // ...

    // the controller can be changed to any PHP callable
    $event->setController($controller);
}

Its unclear to me where to put this block of code. It seems to me that it should go in the Kernel, and if I had the Kernel I wouldn't be having this problem.

My question is, is there an easy way for me to determine if I'm in 'dev' or 'prod' as set in the Kernel, from a Service or Model. Thanks

like image 436
ContextSwitch Avatar asked May 17 '12 17:05

ContextSwitch


4 Answers

The default entity classes generated by the console don't inherit anything. This means they aren't "ContainerAware" in any way.

And generally speaking, I don't think they should be. I supposed it depends on what you're doing but you could handle this with some basic dependency injection

In a controller:

$entity = new \Your\Bundle\Entity\Foo(
  $this->container->get( 'kernel' )->getEnvironment()
);

And then in src/Your/Bundle/Entity/Foo.php

private $env;

public function __construct( $env=null )
{
  $this->env = $env;
}

Would this work for you?

P.S. The event listener you posted about is for Controllers - not for arbitrary classes.

like image 180
Peter Bailey Avatar answered Nov 19 '22 08:11

Peter Bailey


Of course there is the quick and dirty way of globals...

function quickAndDirty() {
   global $kernel;

   if ($kernel->getEnvironment() == 'dev') {
      // we're in dev mode
   }
}

Its bad and evil and you should wash yourself after using it, but in the case of a large existing codebase that you perhaps inherited, it saves a potential refactoring nightmare.

Of course, whether you can live with yourself after using such a method, is up to you ;)

like image 29
Steve Childs Avatar answered Nov 19 '22 07:11

Steve Childs


It's also possible to get that as a parameter. If you take a look at the \Symfony\Component\HttpKernel\Kernel class you'll find a getKernelParameters() method that exposes all the kernel parameters.

/**
 * Returns the kernel parameters.
 *
 * @return array An array of kernel parameters
 */
protected function getKernelParameters()
{
    $bundles = array();
    foreach ($this->bundles as $name => $bundle) {
        $bundles[$name] = get_class($bundle);
    }

    return array_merge(
        array(
            'kernel.root_dir' => realpath($this->rootDir) ?: $this->rootDir,
            'kernel.environment' => $this->environment,
            'kernel.debug' => $this->debug,
            'kernel.name' => $this->name,
            'kernel.cache_dir' => realpath($this->getCacheDir()) ?: $this->getCacheDir(),
            'kernel.logs_dir' => realpath($this->getLogDir()) ?: $this->getLogDir(),
            'kernel.bundles' => $bundles,
            'kernel.charset' => $this->getCharset(),
            'kernel.container_class' => $this->getContainerClass(),
        ),
        $this->getEnvParameters()
    );
}

So in a services.yml file you can get the environment with %kernel.environment% whilst in a container aware class you can get it by doing:

$this->getContainer()->getParameter('kernel.environment');

see Kernel.php class on github

like image 26
Francesco Casula Avatar answered Nov 19 '22 07:11

Francesco Casula


(Note: this works on Symfony 3.x, not sure about 4.x)

You can inject %kernel.environment% straight into your service:

    my_service:
        class: My\Foo
        properties:
            env: '%kernel.environment%'

Then in your service class:


class Foo {

    $env;
    ...
    function someFunction()
    {
        if($this->env === 'dev') {
            // do some dev stuff
        }
        else {
            // do some prod stuff
        }
    }
}

This has the advantage that if you are unit testing you don't need the container.

If you don't like property injection, you can use constructor or setter injection.

like image 2
Henry Avatar answered Nov 19 '22 08:11

Henry