59

What is difference between use env('APP_ENV'), config('app.env') or App::environment() to get app environment?

I know that the env('APP_ENV') will to $_ENV, config('app.env') reads the configuration and App::environment() is an abstraction of all. And in my opinion the advantage is even this. Abstraction.

I do not know if there are other differences, such as the level of performance or security

miken32
  • 42,008
  • 16
  • 111
  • 154
Miguel Borges
  • 7,549
  • 8
  • 39
  • 57
  • 3
    There are no _real_ differences (as the value comes from the same place: your *.env* file) but as a rule of thumb, you should rely on `config()` rather than `env()` directly if you wish to cache your configuration values. – Martin Bean Oct 13 '16 at 16:59

6 Answers6

96

In Short & up-to-date 2022:

  • use env() only in config files

  • use App::environment() for checking the environment (APP_ENV in .env).

  • use config('app.var') for all other env variables, ex: config('app.debug')

  • create own config files for your own ENV variables. Example:
    In your .env:

    MY_VALUE=foo

example config/myconfig.php

return [
    'myvalue' => env('MY_VALUE', 'bar'), // 'bar' is default if MY_VALUE is missing in .env
];

Access in your code:

config('myconfig.myvalue') // will result in 'foo'

Explanation & History:

I just felt over it. When you cache your config file, env() will (sometimes?) not work right. So what I found out:

  1. Laravel recommends only to use env() within the config files. Use the config() helper in your code instead of env(). For example you can call config('app.env') in your code.
  2. When you use php artisan config:cache all the configuration strings are cached by the framework and any changes you make to your .env file will not be active until you run the php artisan config:cache command again.

From this article on Laracast:

UPDATE:
env() calls work as long as you don't use php artisan config:cache. So it's very dangerous because it will often work while development but will fail on production. See upgrade guide

Caching And Env

If you are using the config:cache command during deployment, you must make sure that you are only calling the env function from within your configuration files, and not from anywhere else in your application.

If you are calling env from within your application, it is strongly recommended you add proper configuration values to your configuration files and call env from that location instead, allowing you to convert your env calls to config calls.

UPDATE Laravel 5.6:
Laravel now recommends in its documentation to use

$environment = App::environment();

// or check on an array of environments:
if (App::environment(['local', 'staging'])) {
    // The environment is either local OR staging...
}

and describes that env() is just to retrieve values from .env in config files, like config('app.env') or config('app.debug').

ndberg
  • 3,391
  • 1
  • 21
  • 36
  • 1
    Thanks for this! It's also referenced in the official docs here: https://laravel.com/docs/5.4/configuration#configuration-caching – jeff-h Mar 06 '17 at 06:51
  • It is config('app.env') not config('APP_ENV') – pauloz1890 Jul 29 '18 at 13:34
  • did they change the docs? I did not find that they state anywhere that `App::environment()` is using `config('app.env')`. – Adam Aug 23 '19 at 10:06
  • The .env is where you set all your environment variables, so in the end App::environment() will get it from APP_ENV in the .env file. https://laravel.com/docs/5.6/configuration#environment-configuration – ndberg Aug 23 '19 at 12:51
  • "and describes that env() is just to retrieve values from .env in config files, like config('app.env') or config('app.debug')." - In 2021, Laravel 8.x, `config` should still be used in controllers, etc. no? – JarsOfJam-Scheduler May 26 '21 at 20:58
  • 1
    @JarsOfJam-Scheduler - Yes, in Controllers, etc. you should still use the config() helper. – ndberg May 28 '21 at 20:53
  • A [use case or more about it](https://laraveldaily.com/how-to-add-new-env-variable-so-teammates-would-notice/). – Pathros Jul 31 '21 at 01:54
  • 1
    @ndberg What's the reasoning for using `App::environment()` for env but `config()` for any other variables? I've heard some say that it's worse for performance to return the whole service container instance, but what are the upsides of doing it for the env variable? More secure? – SeaBass Mar 07 '22 at 19:03
  • 1
    @SeaBass Good question. My two points would be: If there is a official way to do something, do it like this - you'll get less problems. Secondly, I like the App::environment(['local', 'special']) helper to check if it's running in one of these environments. I don't thinkt that the performance impact is that big (in normal use cases) – ndberg Mar 09 '22 at 07:50
14

You have two equally good options

if (\App::environment('production')) {...}

or

if (app()->environment('production')) {...}

app()->environment() is actually used by Bugsnag, look in documentation here it says

By default, we’ll automatically detect the app environment by calling the environment() function on Laravel’s application instance.

Now, differences:

1) env(...) function returns null after caching config. It happens on production a lot.

2) you can change config parameters inside unit tests, it gives you flexibility while testing.

Yevgeniy Afanasyev
  • 37,872
  • 26
  • 173
  • 191
5

One thing to consider is perhaps the convenience factor of passing string to app()->environment() in order validate your current environment.

// or App:: whichever you prefer.
if (app()->environment('local', 'staging')) {
    logger("We are not live yet!");
    Seeder::seedThemAll();
} else {
    logger("We are LIVE!");
}
JofryHS
  • 5,804
  • 2
  • 32
  • 39
4

2023 Updated Answer

env() helper works when there is no config.php inside bootstrap/cache directory

config() helper works both in case if the file config.php is present or not. If the file is not present then if will parse the variables at runtime, but if it does find one; it uses the cached version instead.

In production environment the artisan commands we run to add/remove the config file.php becomes of paramount importance in context of how env() and config() behave.

Consider the following example to understand the concept:

Route::get('/', function () {
  // to experiment: set APP_ENV=production in your .env file
  echo 'Via env(): ' . env('APP_ENV') . '<br/>'; // production
  echo 'Via config(): ' . config('app.env'); // production

  /*
  |--------------------------------------------------------------------------
  | run: php artisan config:cache
  |--------------------------------------------------------------------------
  |
  | The config:cache command will generate a configuration cache file (config.php) in the bootstrap/cache directory.
  | At this point, the env() helper will no longer work as all ENV variables will be flushed in favor of the cached config.php file.
  |
  */

  echo '<hr/>';

  echo 'Via env(): ' . env('APP_ENV') . '<br/>'; // null
  echo 'Via config(): ' . config('app.env'); // production

  /*
  |--------------------------------------------------------------------------
  | run: php artisan config:clear
  |--------------------------------------------------------------------------
  |
  | The config:clear command will remove (config.php) configuration cache file from the bootstrap/cache directory.
  | At this point, the env() helper will work again as framework doesn't find a cached configuration file.
  |
  */
  echo '<hr/>';

  echo 'Via env(): ' . env('APP_ENV') . '<br/>'; // production
  echo 'Via config(): ' . config('app.env'); // production
});

So general rule of thumb is to always use config() helper inside your code files; in this way your code does not explode if cached configuration file is available or not.

Now getting the environment is so important and common; Laravel gives us a handful ways we can accomplish the same:

// APP_ENV=production inside .env file

App::environment(); // production
app()->environment(); // production


App::environment('production'); // returns boolean: true
app()->environment('production'); // return boolean: true

Keep in mind you are using App facade or app() helper they all will be using config helper under the hood.

Ali Raza
  • 842
  • 7
  • 13
2

If you are using the config:cache command during deployment, you must make sure that you are only calling the env function from within your configuration files, and not from anywhere else in your application.

If you are calling env from within your application, it is strongly recommended you add proper configuration values to your configuration files and call env from that location instead, allowing you to convert your env calls to config calls.

Add an env configuration option to your app.php configuration file that looks like the following:

'env' => env('APP_ENV', 'production'),

More: https://laravel.com/docs/5.2/upgrade#upgrade-5.2.0

Adam Kozlowski
  • 5,606
  • 2
  • 32
  • 51
0

In 12factor methodology application contains two types of configuration values:

  • internal which not vary between deploys and are stored in laravel ./config/ folder. In this type we usually store some technical optimal/good values used in application which should not be changed by users over time e.g. optimal image compression level, connection timeout, session expiration time etc.
  • external which vary between deploys and are stored in .env file (but should not be stored in git repo, however .env.example with example values with detail info can be stored in repo). In this type we store usually some important/protected values which depends on local environment e.g. passwords, debug mode, db address etc.

Laravel proposes handy approach for this

  • in regular code we use only config(...) helper (so on this level programmer do not need to know which configuration value is internal and which is external)
  • in configuration code external config values should be set using env(...) helper e.g. in config/app.php 'debug' => env('APP_DEBUG', false)
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345