Laravel 5 environment detection - php

I'm trying to get environment detection to work, so that I can use the .env.local.php file and all the other goodies, but somehow I cannot get it to detect the right environment.
I have added bootstrap/environment.php
<?php
$env = $app->detectEnvironment(array(
'local' => array('mylocalmachinename')
));
But when I php artisan env, I always get production instead of local.
Anyone know what the problem is?

Environment detection has changed in Laravel5.
You now put a .env file in the project root
APP_ENV=local
Then on another computer - you might do
APP_ENV=staging
You can then add additional environmental items - i.e.
APP_ENV=local
APP_KEY=SomeRandomString
DB_USERNAME=homestead
DB_PASSWORD=homestead

Related

How to load different mail_driver config setting based on app_env setting in Laravel 5.3 App>

In my PHP Laravel 5.3 app I have my config settings in my .env file with the
APP_ENV=local which can be changed to APP_ENV=production when my app is in production/live mode.
In that .env file I also have a MAIL_DRIVER=preview setting which gets pulled into my config/mail.php config file with env('MAIL_DRIVER', 'smtp') like this:
return [
'driver' => env('MAIL_DRIVER', 'smtp'),
]
So now my question is, when I change my .env setting APP_ENV=local into APP_ENV=production
How can I make it load a different env('MAIL_DRIVER') setting based on that env('APP_ENV') setting?
is there a way to load different .env files for each environment or different config files or how do you handle this in Laravel 5.3.
I remember in older versions of Laravel you simply created a new folder in the config folder for each environment but the whole config system is different from those older versions.
With Laravel 5, you have a different copy of your .env file in each environment.
This file is NOT committed into your repository. Rather, your .env.example file is, and that is what you make a copy of and name as .env in the environment.
In previous versions of Laravel (i.e. <= 4) you could have separate environment files in the same checked out copy of the project and switch between environments, but that doesn't actually make much sense.
Keep your .env.example file up to date with all the options you will need in your app, and initialize them to empty values. When you deploy to a new environment, you copy it as a new file, which keeps you from accidentally committing credentials to your repo and keeps things simple:
cp .env.example .env
Then edit the file and set the values to be appropriate in that specific environment. For example, instead of using test API keys, you may use the production keys for some service. Editing, for example:
sudo vim .env # If you like VIM
or
sudo nano .env # If you like NANO
An exception to what I just said above is with testing. Per the documentation:
You may also create a .env.testing file. This file will override values from the .env file when running PHPUnit tests or executing Artisan commands with the --env=testing option.
In that case though, having your .env.testing file in your repo is most likely acceptable assuming it doesn't contain any sensitive production values, which it probably shouldn't anyway.

Phpunit overriding variable in .env

In my .env file of a laravel 5.1 project i have set the APP_ENV to local, But when i run the test from the terminal the with
vendor/bin/phpunit
the debug and die on
dd(env(APP_ENV));
gives me "testing".
I Have dont a good research on this, tried using the following ways -
trying to set the APP_ENV=local pipelining vendor/bin/phpunit form the cli.
Trying to add env variable in the phpunit.xml file<env name="APP_ENV" value="local" override="true"> (dosent seem to override though)
adding a .env.testing file and setting the APP_ENV=local
in the testCase.php file where the application autoloads $app->loadEnvironmentFrom('.env.testing');
none of the above methods give me the expected result rather everytime i run the test give APP_ENV as "testing".
Not able to trace where is phpunit setting this variable from.
Pls help out!
In vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php search for putenv('APP_ENV=testing'); try to change this to local.
This should work for you, though it is not advisable.

Best practice - Distinguish between environments (PHP)

I need to make some slight configuration changes in my local dev env.
Thus, I would like to know what is the "best practice" in distinguishing between environments.
I would like to have only one config file which will behave differently depending on which environment it is executed.
Common and good practice is to use different .env files on different environments.
Basically, a .env file is an easy way to load custom configuration
variables that your application needs without having to modify
.htaccess files or Apache/Nginx virtual hosts. This means you won't
have to edit any files outside the project, and all the environment
variables are always set no matter how you run your project - Apache,
Nginx, CLI, and even PHP 5.4's built-in webserver. It's WAY easier
than all the other ways you know of to set environment variables, and
you're going to love it.
You can use some already created packages to add this to your project. Check this one: https://github.com/vlucas/phpdotenv
Example (just for a demo, not production ready code!):
Note! You will need to add .env to .gitignore file to keep it not synced between environments.
Development .env file:
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=
Production .env file:
DB_HOST=192.168.10.1
DB_USER=dbUser
DB_PASSWORD=123456
Possible config.php file:
<?php
// add composer autoload somewhere here...
$dotenv = new Dotenv\Dotenv(__DIR__);
$dotenv->load();
return [
'db' => [
'host' => getenv('DB_HOST'),
'user' => getenv('DB_USER'),
'pass' => getenv('DB_PASSWORD'),
]
]

Missing the point: Laravel 5 environment setup

So, for my application I see 4 types of environments it can run under:
Local on my machine
Local on my VM where I am using Homestead
Staging
Production
Each environment differs in the database connectivity (type of DB, connectivity to the DB credentials, etc).
In my bootstrap/start.php I have set up this:
$env = $app->detectEnvironment(array(
'local' => array('localhost'),
'localStaging' => array('mylocalStage.dev'),
'staging' => array('myapp-stage.com'),
'production' => array('myapp.com'),
));
How do I enforce those settings? where do I set up that when I'm on 'local' I will use some local settings? Currently when I use
php artisan env
on my root application folder I get:
Current application environment: production
why isn't it picking up I'm 'local'?
After discussing the issue in the comments and in the chat, the conclusion was to use the new .ENV approach which have been introduced in laravel 5.
Which means, you should have an .env file in your root directory with the current environment's settings.
So for local env, your .env file would have different settings than your production's env .env file.
As default you should have a .env.example file, in case you don't have one - you can copy the default content from the git (.env.example#git).
Please notice that when you're updating (pushing) your local version to staging (for instance), that you don't overwrite the .env file. In order to prevent those kind of issues you can use git ignore (so it will skip that file).

What's the correct way to set ENV variables in Laravel 5?

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.

Categories