31

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

j0k
  • 22,600
  • 28
  • 79
  • 90
ContextSwitch
  • 2,830
  • 6
  • 35
  • 51

4 Answers4

53

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.

Peter Bailey
  • 105,256
  • 31
  • 182
  • 206
20

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

Francesco Casula
  • 26,184
  • 15
  • 132
  • 131
  • I would recommend to call the `parent::getKernelParameters()` method in order to be sure not to forget any parameter if one is added in the next releases of symfony :) `return array_merge(parent::getKernelParameters(), array(...));` – Flo Schild Dec 23 '16 at 10:51
3

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 ;)

Steve Childs
  • 1,832
  • 2
  • 20
  • 26
  • 5
    Please, never do this – Dan Nov 01 '18 at 13:07
  • @Dan: what's wrong with this specific use of globals? If not in a container-aware class it can still be entirely necessary to know whether the site is running in production or not. (At [PHP global or $GLOBALS](https://stackoverflow.com/questions/3573847/php-global-or-globals) they suggest that using `$GLOBALS['kernel']` instead avoids the ambiguity over scope that the code here can create.) – GKFX Mar 04 '19 at 10:38
  • Well, to answer my own question, it turns out that the first thing wrong with this is that `$GLOBALS['kernel']` in production is an instance of AppCache on Symfony 3.4.22, so this crashes with `Attempted to call an undefined method named "getEnvironment" of class "AppCache"`. – GKFX Mar 04 '19 at 10:51
2

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

Henry
  • 7,721
  • 2
  • 38
  • 38