Framework: Serve command loads server in wrong environment

Created on 8 Mar 2019  路  27Comments  路  Source: laravel/framework

  • Laravel Version: 5.8.3
  • PHP Version: 7.2.15
  • Database Driver & Version: sqlite locally (irrelevant I believe)

Description:

When using the artisan serve command the correct environment is not loaded.

Steps To Reproduce:

  1. run php artisan serve --env=testing with a .env.testing file with APP_ENV=testing
  2. put a {{ env("APP_ENV") }} in any view or anything
  3. Instead of testing, see local

It seems the environment is correctly loaded for artisan commands, but not for the resulting server process. Contrast the above with:

  1. run php artisan tinker --env=testing with a .env.testing file with APP_ENV=testing
  2. run env("APP_ENV")
  3. result is as one would expect: testing
bug

Most helpful comment

Try resetting the configuration cache: php artisan config:clear

All 27 comments

Try resetting the configuration cache: php artisan config:clear

This works for me. Can you first please try one of the following support channels? If you can actually identify this as a bug, feel free to report back.

Try resetting the configuration cache: php artisan config:clear

Thanks. I have done this.

I do believe this to be a bug. Steps to reproduce based solely on laravel/laravel:

  1. composer create-project --prefer-dist laravel/laravel test
  2. copy .env to .env.testing
  3. change in .env.testing APP_ENV to testing
  4. add <h1> {{ env('APP_ENV') }} </h1> to welcome.blade.php
  5. run php artisan serve --env=testing

The page will show local, not the expected testing. From within tinker however the correct testing will be shown.

If still unconvinced this is a bug I'll go to one of the support channels.

I can reproduce this. It works in Laravel 5.7.

I can reproduce this. It works in Laravel 5.7.

Correct. I ran into this in 3 apps upon upgrade to 5.8(.3).

That's very odd. I just tested again and I can indeed reproduce it. Not sure why it didn't the first time I tried.

I really can't see what changed it. Nothing really has changed to the ServeCommand.

Maybe this is caused by #27462 and the related PRs. /cc @GrahamCampbell

isnt the env helper meant to only be used in config files?

(not sure if actually related or not)

@rs-sliske We are only using it to demonstrate the issue. config('app.env') doesn't work either.

@rs-sliske We are only using it to demonstrate the issue. config('app.env') doesn't work either.

Correct. Problem is not in the env helper as far as I can see. If I drop a psyshell in index.php it seems that after constructing the $app the actual environmentFile() and related are off. Something in booting the app seems to be wrong, causing the env to be set to the .env instead of the correct file.

To unfamiliar with the inner workings of laravel to help much I'm afraid.

This is caused by the different ways Laravel 5.7 and 5.8 set environment variables.

  • 5.7 sets the variables in $_ENV and $_SERVER and calls putenv().
  • 5.8 only sets the variables in $_ENV and $_SERVER.

Adding getenv() and putenv() to Laravel 5.8 fixes the issue: https://github.com/staudenmeir/framework/commit/2e1d6a95631aec49510e1b610074e9c25d7842b5

All the tests still work. Can you approve this @GrahamCampbell?

I tried upgrading Lumen, and it broke my app for me. The problem was that it wasn't seeing a required env variable set with export before starting the app.

I gather that Dotenv switched from using getenv to $_ENV due to threading issues with the former, the problem is that $_ENV only gets populated with the existing environment if E is part of variables_order which isn't standard. Standard PHP install on Ubuntu doesn't include it (I believe it's a security measure). A bit of asking around shows that and at least some OSX installs doesn't either, and for docker containers it's a tossup (pretty much everything based on Ubuntu will probably have the problem).

I think that not using put/getenv was an explicit choice, but considering the amount of people that'll get hit by this, whether some compatibility fix can be done. Maybe preloading $_ENV from getenv if the former is empty when starting up. @GrahamCampbell is probably the person to talk to.

@staudenmeir PutenvAdapter was specifically removed to make the env helper read-only. Can we fix this any other way?

Why is it adding putenv fixes this?

@GrahamCampbell it's not putenv that fixes it, but the fact that PutenvAdapter uses getenv to read env variables.

@xendk You need both getenv() and putenv() to fix the issue (if variables_order doesn't contain E).

@driesvints Why is getenv() not read-only?

@GrahamCampbell I don't fully understand it. Somehow, php -S treats getenv()/putenv() and $_ENV/$_SERVER differently.

@staudenmeir You do? Why? The problem with PutenvAdapter is that it shadows EnvConstAdapter for setting too so all variables is then set with putenv() and doesn't show up in $_ENV anymore.

@xendk php artisan serve --env only works for me when I add the PutenvAdapter to LoadEnvironmentVariables::createDotenv() and env().

@StanAngeloff yeah, and that completely shadows EnvConstAdapter. You might want to try and hack EnvConstAdapter::get to try using getenv if the key was not found in $_ENV instead, and see if that doesn't fix things too.

I'm suffering the same issue here:
https://github.com/laravel/framework/issues/27949

Removing the PutenvAdapter adapter breaks loads of third-party composer libraries too.

Here's another issue related to this:

https://github.com/laravel/framework/issues/27913

This has been fixed in the latest release 5.8.7.

This has been fixed in the latest release 5.8.7.

Thanks a lot!

Thanks for everyone's feedback and help with this.

I have liberated Laravel 5.7's env() from the dustbin of the git repo and made it its own package. What's more, using some real composer hacks, I have ensured that it will always be autoloaded first, overriding whatever Laravel's current env() does.

Benefits:

  • Works with any package, even non-Laravel ones (it was my secondary reason)
  • You no longer have to fear Laravel just going one day "Oops! We're not going to read from the environment anymore! Too bad!" on a non-major release.

https://github.com/phpexpertsinc/Laravel57-env-polyfill

To install: composer require phpexperts/laravel-env-polyfill.

Was this page helpful?
0 / 5 - 0 ratings