After upgrade from 5.0 to 5.8, laravel stopped reading env variables if the env is different than .env file.
For example, if i have .env file with the USE_SSL=true inside it.
env('USE_SSL') will be true
But if i have .env file pointing to another env:
APP_ENV=dev
and than i'll have .env.dev file containing USE_SSL=true , env('USE_SSL') will be null.
I tried composer dump-autoload and php artisan config:clear, and php artisan config:cache - no luck. cached or not, i can't get the value.
I tried naming the files .dev.env and .env.dev - no luck.
Any ideas would be appreciated.
I'm adding this as an answer, but please note this isn't how .env file should be used according to laravel docs. It's just a way i needed to use due to some restrictions which required me to use different config files for each env, and load it in runtime. For correct usage of .env file check the docs.
This is a way of loading different config files in runtime depends on where the APP_ENV is pointing. I'm marking this as answered since it's answering this specific question.
.env
APP_ENV=specific_domain
.env.specific_domain
USE_SSL=true
Http/Kernel.php
public function __construct(Application $app, Router $router)
{
parent::__construct($app, $router);
$app_env = explode("=", file($app->environmentFilePath(), FILE_IGNORE_NEW_LINES)[0])[1];
$app->loadEnvironmentFrom(".env.$app_env");
}
Alright if you really wanted to do this,
Route::get('renderEnvChaining',function(){
$myCustomEnv = parse_ini_file(base_path(env('CUSTOM_ENV')));
return $myCustomEnv['USE_SSL']; // This will return true
});
In my .env file i've mentioned this,
CUSTOM_ENV=.env.example
Now i in default env.example i put this
USE_SSL="true" // This will return true
USE_SSL=true // This will return 1
I just found that .ini and .env follows the same values, so i parsed .env file as .ini file,
Give this a try, i've never done this thing before, please concern with other developers before running this into production server
Related
I would like to ask how can I possibly dynamically load different env file setting?
I have read the documentation, I have created two files (.env and .env.uat)
.env for development and .env.uat for client testing environment, and it depends on the url to use different env file, eg: (company-dev) -> .env, (company-uat) -> .env.uat
I have added these two lines of code to bootstrap/app.php, actually it works, but when I want to execute php artisan migrate, then it said that HTTP_HOST couldn't found, so it will load the .env.uat as the fallback file. Can someone tell me where should I modify code please? Thanks!! (Actually I knew I can manually change the .env file in different environment everytime, I am seeking some automatic way to recognise the env file for me.
$envFile = $_SERVER['HTTP_HOST'] == 'xxx-dev-testing.com' ? '.env' : '.env-uat';
$app->loadEnvironmentFrom($envFile);
There's no HTTP_HOST in the command line. You'll need a different approach. Ultimately, though, .env shouldn't be in version control at all. Your UAT environment would just have a .env with different values.
I stumbled across this https://laravel.com/docs/5.4/configuration#configuration-caching in the documentation and it confused me a bit.
When I want an environment variable I use the env() function to return what I want. According to the above link it says I should be using the config() function instead to ensure that on production I am accessing the values through a cache.
e.g. These both return the same thing
env('APP_URL')
vs
config('app.url')
So should I be using config() or env() inside my app?
I assume that if I add a new env variable I will also need to update my config files?
You should never use env() in the code directly. It's a good practice to use config(). In config files use env() to get the data from .env file.
In this case, you can easily override config values at runtime or during testing.
You also can use config caching.
To give your application a speed boost, you should cache all of your configuration files into a single file using the config:cache Artisan command.
Another reason is described in the docs:
You should typically run the php artisan config:cache command as part of your production deployment routine. If you execute the config:cache command during your deployment process, you should be sure that you are only calling the env function from within your configuration files.
Ok, I just started with Lumen and I'm trying to use the Auth, but a call to either Auth::check or any other function of Auth.. leads to the below Error
Fatal error: Class 'Memcached' not found in vendor\illuminate\cache\MemcachedConnector.php on line 52.
I don't want to use Memcached never used it before.
I disabled it in the .env file and set the CACHE_DRIVER and SESSION_DRIVER to array, but still shows the same error.
I decided not to use Auth again and to manually handle my authetication with sessions/tokens, but enabling the MiddleWare StartSession results to the same error.
$app->middleware([
// 'Illuminate\Cookie\Middleware\EncryptCookies',
// 'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
'Illuminate\Session\Middleware\StartSession',
// 'Illuminate\View\Middleware\ShareErrorsFromSession',
// 'Laravel\Lumen\Http\Middleware\VerifyCsrfToken',
]);
Please I'd be so glad if anyone can really help me out here
EDIT
After going A little Deep in the framework
I Hard Coded the session driver name in the SessionManager Class
within the method getSessionConfig
public function getSessionConfig()
{
$this->setDefaultDriver("cookie");//I added this line
return $this->app['config']['session'];
}
It works though but not a good way of doing things.
There is no config file, i believe all configurations are written in .env file, but i really don't know why the session_driver and cache_driver is defaulted to memecached even after changing it in the .env and then ran composer dump-autoload ... Lumen :(
EDIT
This is my .env file
APP_ENV=local
APP_DEBUG=true
APP_KEY=SomeRandomKey!!!
APP_LOCALE=en
APP_FALLBACK_LOCALE=en
DB_CONNECTION=mysql
DB_HOST=localhost
DB_DATABASE=test
DB_USERNAME=root
DB_PASSWORD=
CACHE_DRIVER=array
SESSION_DRIVER=cookie
QUEUE_DRIVER=database
I already have this line uncommented in my bootsrap/app.php
Dotenv::load(__DIR__.'/../');
My DataBase configuration works perfectly so the .env file is loaded
quite alright.
I spent 3 hours on this problem today. With the help of the post of demve in this topic, I found the solution. Very simple! I hope it won't affect me later in my development.
Just to it, in the .env file :
CACHE_DRIVER=array
SESSION_DRIVER=array
QUEUE_DRIVER=array
Ok, I make an UPDATE because I was faced with a new problem about the session. In fact, when you set the previous parameters, your session won't be persistent, like said in the documentation: array - sessions will be stored in a simple PHP array and will not be persisted across requests.
So I have to change it, always in .env a file like that :
SESSION_DRIVER=cookie
With a var_dump(Session::all()); I now can see the whole values of my session
You may need to restart your server, especially if you're using php artisan serve.
Lumen doesn't appear to pick up .env changes per-request.
I had exactly the same issue - trying to use file cache, but received errors regarding Memcached - restarting the server reloads the .env file.
This issue resolved when i installed this package so try at least
First i tried this and it works fine
CACHE_DRIVER = array
but then thought about what is memcached
Then i tried this and it works fine without changing driver memcached
apt-get install php-memcached
yum package manager or in Amazon Linux.
yum install php-memcached -y
In .env file replace
#This line:-
CACHE_DRIVER = memcached
#With this:-
CACHE_DRIVER = array
Make sure not to get caught out by your .env file not being loaded, which by default it's commented out in Lumen. So if you are specifying a different cache driver in your .env, do the following.
Note: If you are using the .env file to configure your application, don't forget to uncomment the Dotenv::load() method in your bootstrap/app.php file.
Source: http://lumen.laravel.com/docs/cache
in your .env file, you can also use CACHE_DRIVER=file instead of CACHE_DRIVER=memcached
In my case i added Add CACHE_DRIVER=array in .env file
Then
Dotenv::load(__DIR__.'/../');
in my bootstrap/app.php and the .env file started working.
For me, the issue was that I used the php-7 branch of homestead repository which does not have PHP memcached ready.
I had a similar problem now, I couldn't track it down but my guess is that it has something to do with the fact that the defaults configurations are stored in the vendor/laravel/lumen-framework/config folder, the DotEnv::$inmutable setting and the artisan serveserver.
The solution that worked for me was:
Add in bootstrap/app.php the following:
Dotenv::makeMutable();
Dotenv::load(__DIR__.'/../');
Dotenv::makeImmutable();
in the .env file, set all the configuration to "basic drivers" (array, file) even if you are not going to use them, because you w
If you have a new lumen installation,
you must rename .env.example to .env . So it can read your configurations!
This happens if your .env file is owned by another user than the one trying to run the artisan command.
Check if memcached is installed, if not install it by running:
apt-get install php5-memcached
I installed fresh Laravel 5 copy.
My detectEnvironment function is defined this way:
$app->detectEnvironment(function()
{
return 'local';
return getenv('APP_ENV') ?: 'production';
});
In config\local I've created database.php file:
<?php
return [
'nothing' => 'new',
];
I run php artisan clear-compiled.
My index method of WelcomeController is defined this way:
public function index(Application $app)
{
echo $app->environment();
var_dump($app['config']['database']);
//echo $app['config']['database'];
return view('welcome');
}
Application was imported this way: use Illuminate\Foundation\Application;
The result I get is:
local array(1) { ["nothing"]=> string(3) "new" }
whereas I would expect Laravel to cascade config file with production one (with the default config\database.php file.
The strange thing is that even if I comment the line return 'local'; run again php artisan clear-compiled it shows:
production array(1) { ["nothing"]=> string(3) "new" }
so it seems it always loads database.php file content (this one from local folder) and overrides main database.php file. It works fine again when I change this file name to for example aaa.php.
Is it a bug or maybe environment configuration shouldn't be stored inside config directory? But if not, where should they be store? I don't know if it's a bug or a feature so if anyone knows more about it, please give me a clue.
Although in documentation for Laravel dev (5.0) there is info that configuration will cascade it's not true. I have tested it about 2 weeks ago and it seems at the moment the only way to have different values for environments is using ENV file where you put custom values for current environment. Putting settings in directories won't work as it used to work however it's possible it will change or maybe has been already changed for last 2 weeks.
There's a package that brings the cascading config system back to Laravel 5.
Disclaimer: I am the author.
For me it looks like defect in Laravel 5 dev branch. I was able to work around by adding manual environment detection and configuration. This code does it.
'default' => $app->environment()=='testing'?'sqlite':'mysql',
It is easy to configure Laravel 5 environment.
Open your root application folder and find ".env.example",
Copy and rename into ".env",
Please fit ".env" file into your environment,
If you use GIT, make sure you don't push this file to your GIT repository.
For 'complete explanation', I write this configuration here.
Edited;
I quote from the developer in His github repository readme.md file;
phpdotenv is made for development environments, and generally should
not be used in production. In production, the actual environment
variables should be set so that there is no overhead of loading the
.env file on each request. This can be achieved via an automated
deployment process with tools like Vagrant, chef, or Puppet, or can be
set manually with cloud hosts like Pagodabox and Heroku.
So, you need to create ".env" file per machine and don't use ".env" file in your production server.
In laravel 4 we had:
$env = $app->detectEnvironment(array(
'local' => array('homestead')
));
by default.
But in laravel 5 it's changed to:
$env = $app->detectEnvironment(function()
{
return getenv('APP_ENV') ?: 'production';
});
Also, they have excluded .env.* line in .gitignore, now it has:
.env
And added file .env.example:
APP_ENV=local
APP_KEY=SomeRandomString
DB_USERNAME=homestead
DB_PASSWORD=homestead
So, if i have more than 2 environments, do i have to set all of them in a single .env file now? E.g.:
APP_ENV=local
DB_PASSWORD=123
APP_ENV=alpha
DB_PASSWORD=456
If i would have no .env file, how laravel will know what environment i am using?
You can do it exactly the same as in Laravel 4:
$env = $app->detectEnvironment(array(
'local' => array('homestead')
));
*.env file are just used to put sensitive data that shouldn't be put into VCS. The same is in Laravel 4
but is seems that in last days default detectEnvironment was changed to:
$env = $app->detectEnvironment(function()
{
return getenv('APP_ENV') ?: 'production';
});
so you can use either setting variable from PC name or from ENV file.
If you use ENV based environment detection in main env file (by default .env file you need to add:
APP_ENV=local
Of course local here is local environment, you can change it into production or dev
At the moment the most important issue I see is that you need to remember when going on production to change this .env file content from APP_ENV=local to APP_ENV=production so in my opinion much better method is the old default method based on PC names.
Now ENV files. If you use ENV based environment detection, you should put into your ENV file only:
APP_ENV=local
Now you can create separate ENV files for your different environments for example:
.local.env :
MY_DB=testdb
.production.env :
MY_DB=productiondb
and now in bootstrap.environment.php file you can modfiy:
if (file_exists(__DIR__.'/../.env'))
{
Dotenv::load(__DIR__.'/../');
}
into:
if (file_exists(__DIR__.'/../.env'))
{
Dotenv::load(__DIR__.'/../');
if (getenv('APP_ENV') && file_exists(__DIR__.'/../.' .getenv('APP_ENV') .'.env')) {
Dotenv::load(__DIR__ . '/../', '.' . getenv('APP_ENV') . '.env');
}
}
to load extra env file based on APP_ENV from main env file.
Now you will be able to use it in your other configuration file as always: $_ENV['MY_DB']
For those who just upgraded to 5.2:
You cannot longer use the static Dotenv::load() method. Use the following instead:
$dotenv = new Dotenv\Dotenv(__DIR__ . '/../', '.' . getenv('APP_ENV') . '.env'); // Laravel 5.2
$dotenv->load();
in bootstrap/app.php.
//edit
Soo.. after digging into this for the past hour I might as well add some additional info here:
Laravel uses .env files for configuration
By default, the file ".env" in the root directory of the application is loaded
You can access the values within those .env files via the env() helper function or directly via PHP's native getenv() function. Although you should only do so to fill your config files (see /config/*.php), because those can be cached.
the .env files are loaded in the DetectEnvironment class. I found this helpful while debugging to set breakpoints. Please take note of the line (new Dotenv($app->environmentPath(), $app->environmentFile()))->load();: Since it uses load() any environment value that has already been set will not be overwritten! (You would have to use overload() to do so - this drove me nuts because homestead sets the APP_ENV variable to local in the php-fpm config /etc/php/7.0/fpm/php-fpm.conf and you cannot change it via .env file)
when writing unit tests, you usually inherit from TestCase, which sets the APP_ENV variable to testing (via refreshApplication() -- using putenv() to override the default local value)
I just wanted to contribute my solution for Laravel 5.1, which is slightly simpler IMHO. In bootstrap/app.php, I have (just after where the Application is instantiated):
$app->beforeBootstrapping(\Illuminate\Foundation\Bootstrap\DetectEnvironment::class, function() use ($app) {
$suffix = (env('APP_ENV'))
? '.'.env('APP_ENV')
: '';
$app->loadEnvironmentFrom('.env'.$suffix);
});
There's no need for any checking or error handling. Laravel will default to "production" if the file is not found.
That is all.
The fact that you can't have more than one .env file by default and that it's excluded in .gitignore is intentional and is the intended way to manage environments. The .env file should not be in version control and should be configured per environment. .env sets your environment and all environment variables.
So, if i have more than 2 environments, do i have to set all of them
in a single .env file now?
No. You would have a .env file in each place that you have your application installed. The difference is in what is inside that file.
Additionally, because the .env file is simply a key-value store, any subsequent declarations would overwrite previous ones. In your example, Laravel would never see your "local" settings.
It seems odd at first, but this new default system is actually generally easier and less prone to the issues the "4.2 way" had/has, as there's no place for logic errors.
If i would have no .env file, how laravel will know what environment i am using?
It wouldn't run at all. In the .env file is also an APP_KEY declaration, which Laravel will not run without. Without a .env file, you would get a 500 server error.