Best practice - Distinguish between environments (PHP) - 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'),
]
]

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.

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).

How to have environment specific .env files for dotenv (in Laravel 5)

I've just started using Laravel 5 which uses the dotenv library. This uses a .env file in the root of the project which sets the environment with this line:
APP_ENV=local
According to everything I've read on the subject, all other environmental specific configuration should be placed in this file, so database passwords, urls etc, which are then read into the main config array like this:
env('DB_HOST', 'localhost')
While I feel this may work for a few specific things like database passwords that you might not want committed, what I really want is to be able to commit most or all of my different environmental values for each environment.
Thus what I want is for .env to define APP_ENV as "local", "staging" or "production" and then have a .local.env or .env.local file containing the values, which I can then commit and the correct file will be loaded based on APP_ENV.
Is this possible? Laravel 4 had the cascading config arrays which seemed a lot more flexible but if I can have an environmental .env file then I can live with that.
Solved it in the end by modifying app/Providers/ConfigServiceProvider.php. This file is added as a stub to your app folder when you create a project and is intended for overriding config values.
It now handles the cascading configs, so that any values in config/local/app.php for example will override config/app.php. As the comment below says it doesn't handle matching arrays in the environment config and will just replace then. But I can solve that when I need it.
<?php namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Symfony\Component\Finder\Finder;
class ConfigServiceProvider extends ServiceProvider {
/**
* Overwrite any vendor / package configuration.
*
* This service provider is intended to provide a convenient location for you
* to overwrite any "vendor" or package configuration that you may want to
* modify before the application handles the incoming request / command.
*
* Modified 2014-01-20 to allow environment specific configs to be loaded
* from app/config/[environment]/ which will cascade over the base configs.
*
* #return void
*/
public function register()
{
$config = app('config');
$envPath = app()->configPath() . '/' . getenv('APP_ENV');
foreach (Finder::create()->files()->name('*.php')->in($envPath) as $file)
{
$configName = basename($file->getRealPath(), '.php');
$oldConfigValues = $config->get($configName);
$newConfigValues = require $file->getRealPath();
// Replace any matching values in the old config with the new ones.
// Doesn't yet handle matching arrays in the config, it will just replace them.
$config->set($configName, $newConfigValues + $oldConfigValues);
}
}
}
You dont have to use .env for everything. There are a few options.
Option 1 - Use only .env for a variable
'default' => env('DB_CONNECTION'),
Option 2 - Use only .env for a variable, but have a system default if none exists
'default' => env('DB_CONNECTION', 'mysql'),
Option 3 - just hard code your variable and not make it settable via the .env
'default' => 'mysql',
Option 2 is probably the best for most config options. You still define (and commit) an option for your config to your git repo - but you can easily override it in any .env file in the future if you want.
Option 1 is best specifically for passwords, app keys etc - so they are never committed to your git repo.
Option 3 is for a few config variables which you know will just never change.
Note - the cascading Laravel 4 config folder option is no longer available.
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.
I quote from the dotenv developer;
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.

Trying to Migrate in Development Mode

I'm trying to figure out how I can get my environment set to development mode inside my Laravel application.
bootstrap/start.php
$env = $app->detectEnvironment(array(
'development' => array('blog.app'),
'production' => array('')
));
Inside my routes file I have the following:
Route::get('/', function()
{
dd(App::environment());
});
When I go to blog.app it says its set to production and I'm not sure why. The purpose of figuring out why its giving me production instead of development is because I am attempt to run the command "php artisan migrate" and its giving me the following.
My-iMac:blog my$ php artisan migrate
**************************************
* Application In Production! *
**************************************
Do you really wish to run this command?
So I need help understanding why its still saying application is in production mode when I'm attempting to be in development mode.
Go inside your project directory. Then navigate to bootstrap/start.php.
Edit the local array specified in $app->detectEnvironment with your machine name.
Laravel will automatically check you machine name every time and know that it is a local environment and use the local configuration files instead. To use the local config files you can navigate to app/config/local and edit the files there. The files in app/config belong to the production environment. You can copy these files in the local folder and then edit them accordingly, for example you database configuration probably will differ on your local machine and the server.
You can simply edit the files in the config folders and Laravel will detect automatically the environment according to the array in the start.php and use the config files related to the machine on which you are working. You can also specify more environments and create their entries in the start.php file and then go and create a folder by the same name in the app/config folder and create config files for that environment in that folder.
Example: If you want to have two local environments you can edit you start.php file like so
$env = $app->detectEnvironment(array(
'local' => array('Machine1', 'Machine2'),.
'local2' => array('Machine3', 'Machine4'),
));
And then navigate to the app/config folder and create two folders like local and local2 and have separate files for each of them. Now the machines with names Machine1 and Machine2 will automatically use config files present in local folder and Machine3 and Machine4 will use config files in local2 folder. This way Laravel provides great flexibility in setting environments.
For more information check out the Environments and Configuration Episode on Laracasts.
You need to figure out your machine name. In order to do that, run this code anywhere:
echo gethostname();
exit;
More info about the function: http://php.net/manual/en/function.gethostname.php
It will output your machine name, then you need to paste it in the 'development' array.

How to make ZF2 db credentials environment specific

I am starting a new project.
I am using ZF2. I have just installed it and have the Skeleton application up and running.
This is my deployment process:
I develop on my local machine
I then push to my public github repository
I then use deployhq.com to deploy those to my production
server which is where the user would see the changes made.
I have tried to look around stack, zend site, and google at blogs etc but still dont have any real understanding or solution to my problem.
I want the application to use different database credentials based on its environment. E.g. if on 'dev', my local machine, then use credentials A, but if on live server, then use credentials B.
I have read a lot about global and local autoload config files etc, but baring in mind my github repo is public, any where I commit any config files with my db details would be visible.
I was wondering if there was a way to have, the same theory, global and local files with the DB connections in, i upload the production details manually, not via git for security reason, and tell git to ignore the local config file somehow? I would also need to know how I tell the application to use those config files based on the environment and there location.
In Zend 2 There are
Global configuration file &
Module level configuration file
IF you want to know there use you can refer the link below
How does configuration works in ZF2
When I had a same scenario I used the above link to understand and exploit Zend Config module which is really good to handle the situation like this .
create two files
production.php
local.php
in both these files
return this array based on the environment
return array(
"dbname" => "yourdbname"
"dbhostname" => "dbhostname"
"dbusername" => "yourdbusername",
"dbpassword" => "yourdbpassword"
);
in config/autoload/ directory of your zend framewrok application
later edit your config/application.config.php file as per below instructions
// get the application env from Apache vhost file ( here you can set in your apache vhost file as production or local )
$applicationEnv = getenv('APPLICATION_ENV');
$environmentSpecificConfigPath = "config/autoload/{,*.}{".$applicationEnv.",local}.php";
// Next with in the config array pass the environment specific configuration path
'config_glob_paths' => array($environmentSpecificConfigPath)
in any controller or action
you can just use the below code
$configArray = $this->getGlobalConfig();
Now $configarray has all your DB credentials to create a connection
$adapter = new Zend\Db\Adapter\Adapter(array(
'driver' => 'Mysqli',
'database' => $configArray['dbname'],
'username' => $configArray['dbusername'],
'password' => $configArray['dbpassword']
));
If you use config array to connect the DB in your entire application
you dont need to worry about environment changes just make sure you have an Apache APPLICATION_ENV entry in your vhost file
you can do that by adding below line in your apache vhost file
SetEnv APPLICATION_ENV "production" // in your production server
SetEnv APPLICATION_ENV "local" // in your local
Also Last but not least you can use the Zend Experts module ZeDB
https://github.com/ZendExperts/ZeDb
To manage your CRUD applications
Hope the above steps may help you in creating the environment

Categories