42

When using dev mode with a Symfony2.x application, one usually works in locale. Hence, such function does not works as expected (for instance, try to get the current IP under localhost). This could be a problem, e.g. when one try to use such ip-based web service. Hence, I just want to know how to check inside a controller if the Symfony2 application is running in dev mode or not. In that way one can set the behavior of the controller depending by the mode.

Any idea?

Niket Pathak
  • 4,417
  • 1
  • 30
  • 38
JeanValjean
  • 15,832
  • 22
  • 103
  • 145
  • Can I suggest you to take a look at my answer which I think is more appropriate than the accepted one? – Veve Feb 02 '17 at 15:31

9 Answers9

60

To get the current environment in a Controller you can use:

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

So you just put that in an if() statement to check if it equals to dev.

Gottlieb Notschnabel
  • 8,768
  • 17
  • 66
  • 107
tolgap
  • 9,133
  • 10
  • 45
  • 63
27

As of Symfony 2.5 it could be done as:

$this->container->get('kernel')->getEnvironment();

Directly asking Kernel of it's environment looks nicer than searching for parameter.

Damaged Organic
  • 6,819
  • 5
  • 48
  • 77
  • I think it's related to passing Container anywhere outside Dependency Injection Container. That's a bad practise due to tree circularity. I could provide full answer if you need. – Tomas Votruba Oct 23 '17 at 19:11
  • @TomášVotruba: Please do. From my point of view retrieving such meta from container is harmless, as it just uses reference to the container which is `public` property of DIC. If Symfony developers wanted it to be considered bad practice, they would rather create shortcut methods for encapsulation. – Damaged Organic Oct 24 '17 at 06:40
  • Done, I've tried to added some explation you've requested. It's another topic and it would make answer less readable, so I tried to make it short. Definitelly check the link, it explains a lot :) – Tomas Votruba Oct 24 '17 at 13:04
  • "If Symfony developers wanted it to be considered bad practice..." - These changes takes time, because many people including leader have to agree upon them. That's why some frameworks used contructor injection by default since 2015 and Symfony waited till late 2017 and Symfony 4. – Tomas Votruba Oct 24 '17 at 13:06
  • @TomášVotruba: Got you point, thanks. However, at the time of writing it was a reasonable option. – Damaged Organic Oct 24 '17 at 14:40
  • @KinBinary: No argument here. I think my answer will be outdated in 1-2 years with some better replacement. – Tomas Votruba Oct 24 '17 at 16:21
  • 2
    @TomášVotruba: Just another day in software development: ) – Damaged Organic Oct 24 '17 at 20:44
17

Since you want to know if you are in dev mode (not necessarilly the environment named "dev"), you can retrieve the kernel from the service container and check the isDebug method return:

$kernel = $this->get('kernel');
$devMode = $kernel->isDebug();

As noted in the documentation (emphasis is mine),

Important, but unrelated to the topic of environments is the true or false argument as the second argument to the AppKernel constructor. This specifies if the application should run in "debug mode". Regardless of the environment, a Symfony application can be run with debug mode set to true or false. This affects many things in the application, such as displaying stacktraces on error pages or if cache files are dynamically rebuilt on each request. Though not a requirement, debug mode is generally set to true for the dev and test environments and false for the prod environment.

Internally, the value of the debug mode becomes the kernel.debug parameter used inside the service container.

Veve
  • 6,182
  • 5
  • 37
  • 53
16

Symfony 3.3/4/5+ Solution

Here is 2017 and Symfony 3.3+ version using Constructor Injection.

Instead of passing you whole application (= container), you could pass only the parameter you need:

1. Service config

# app/config/services.yml
services:
    _defaults:
        autowire: true

    App\Controller\SomeController:
        arguments: ['%kernel.environment%']

If you don't understand this syntax, check this post explaining Symfony DI news in before/after examples.

2. The Controller

namespace App\Controller;

final class SomeController
{
    /**
     * @var string
     */
    private $environment;

    public function __construct(string $environment)
    {
        $this->environment = $environment;
    }

    public function someAction()
    {
        $this->environment...
        // any operations you need
    }
}


Why to avoid passing Container in Controller?

The most important thing in the code is consistency.

  • If you prefer static and service locators (= service you can pass anywhere to get any other service), use it.

  • If you prefer constructor injection, tree dependency graph (!= circular dependencies), use it.

Mixing this concept might be ok for you, if you know why you used them that way. But here comes to play The Broken Window Theory (nicely described version by Coding Horror). Anyone coming to the code will more likely pick the version that is not intended to use that way.

Ambiguity in the code is the first invitation to legacy code

I've mentored teams of many applications, that started with simple $this->container in the code and after couple of years ended up calling me for help, how to rewrite or refactor whole static hell.

Tomas Votruba
  • 19,054
  • 8
  • 65
  • 86
  • 7
    Great, but use `'%kernel.debug%'` instead of `'%kernel.environment%'` and `bool $isDebug` as constructor's parameter. – kpower Nov 15 '18 at 20:00
4

From Symfony 4.1 inside Service

class MyService
{
    private $params;
    public function __construct(ParameterBagInterface $params)
    {
        $this->params = $params;
    }
    public function check($e)
    {
       if($this->params->get("kernel.environment") === "dev") 
       {
            return true;
       }
    }
}
4

Symfony 5.1

$this->devEnvironment = 'dev' === getenv('APP_ENV');

I use this inside of a Symfony service. You will need to add the line APP_ENV=dev to .env.local and APP_ENV=prod to .env file. Depending on if you have a similar env setup to me

Luke Pring
  • 878
  • 2
  • 10
  • 15
3

In Symfony 4 and higher, you can use simply :

if ($this->getParameter('kernel.environment') === 'dev') {
    // ...
}
Vincent Decaux
  • 7,375
  • 3
  • 37
  • 52
0

For Symfony 4.1+

I prefer to avoid using kernel inside my controllers and services.

services.yaml:

parameters:
    app.environment: '%kernel.environment%'
    ...

Your controller / service:

class MyService
{
    private $isDev;

    public function __construct(ParameterBagInterface $appParams)
    {
        $this->isDev = $appParams->get('app.environment') === 'dev';
    }

    public function doSomething()
    {
        if ($this->isDev)
        {
            ...
        }
    }
}
Erdal G.
  • 1,830
  • 2
  • 19
  • 32
-3

For Symfony 4.x and above

If you are using .env to store your environment variables, you can access them in any controller by simply using $_ENV['name-of-variable']

For a default installation, there is a $_ENV["APP_ENV"] variable available, which will tell you if you are in dev mode or not.


Use print_r($_ENV); to see all the available environment variables.

[ps - This also works for Symfony 3.4]


Reference - https://symfony.com/doc/4.3/components/dotenv.html

Community
  • 1
  • 1
Niket Pathak
  • 4,417
  • 1
  • 30
  • 38
  • You shouldn't be using globals in Symfony. – Dan Nov 28 '19 at 14:41
  • Agreed. But to check something as trivial as whether we're in Dev mode or not, why not? (Just listing out a possibility here) – Niket Pathak Nov 28 '19 at 15:45
  • One of the first rules of Symfony best practises, do not use globals. Something like binding an environment variable would be much better: `$appEnv: '%env(APP_ENV)%'` – Dan Nov 28 '19 at 22:36
  • you're probably right, but the official docs list this way of accessing `env` variables. Kindly check out the reference. – Niket Pathak Feb 27 '20 at 11:27