Pair program with me! profile for carousel at Stack Overflow, Q&A for professional and enthusiast programmers

2/01/2014

Laravel environments setup

Why does it matters ?

Ability to have multiple environments and to switch between them quickly is of big importance for any non-trivial web development task.
For example, if you test your application data layer, test code shouldn't be hitting real database tables in any case. Instead it should rely on mocked and prototyped tables that is easy to create and drop.
Laravel makes that process very easy by offering three main types of environments:

  1. development
  2. production
  3. testing
How to choose environment ?

Entry point for choosing is located in bootstrap/start.php file in the root folder of Laravel project, at ine 29 (Laravel version 4.1):

Original function looks like this:

$env = $app->detectEnvironment(array(
 'local' => array('your-machine-name'),
));


As can be seen, env is detected by providing array with env name and value in the form of key-value pair.

My custom version looks like this:
$env = $app->detectEnvironment(function()
{
    return getenv("ENV") ? : "local";
});


Instead of array, this function accepts function(closure) that returns type of env. That type will be auto deteced with the use of ternary operator.

How to setup environment ?

By just choosing, we didn't do much. We have to customize desired env and tell Laravel when to find them. All env settings are stored under app/config directory.  Default env is production, so if you don't create new, Laravel will treat all config settings as production. Easy task of setting custom env is done by just creating new folder under app/config directory. So if you want to have one env for development and one for production, just create new folder and name it development. Now all that we place inside will be red by Laravel only in case we explicitly choose in bootstrap/start.php file.  Note that development is just a convention, I instead name my development env as local - It is easier that way for me to differentiate. Name is not important, as long as it is in sync with name of the folder and vice verse. Most common reason to have different env are a database settings. By default, they are stored in app/config/database.php file. 

Here is my  database.php file, placed under app/local/ directory:
array(
  'mysql' => array(
   'driver'    => 'mysql',
   'host'      => 'localhost',
   'database'  => 'local-db',
   'username'  => 'root',
   'password'  => '123456',
   'charset'   => 'utf8',
   'collation' => 'utf8_unicode_ci',
   'prefix'    => ''
        )
)];


These setting works under local environment  common ( apache, localhost, mysql configuration ).

 And here are production settings: 
array(
  'mysql' => array(
   'driver'    => 'mysql',
   'host' => getenv("DB_HOST"),
   'database' => getenv("DB_NAME"),
   'username' => getenv("DB_USER"), 
   'password' => getenv("DB_PASSWORD"),
   'charset'   => 'utf8',
   'collation' => 'utf8_unicode_ci',
   'prefix'    => ''
      )
)];


Note that in order for these production values to have affect, you'l have to "catch" env variables that are specific to server environment.
Here I simply import them with native PHP getenv function.

Last and not so commonly used is testing environment. It is provides automatically by Laravel, so you don't have to worry about that. 

Here is how Laravel detects if we are using testing env:

public function createApplication()
 {
  $unitTesting = true;

  $testEnvironment = 'testing';

  return require __DIR__.'/../../bootstrap/start.php';
 }

This is excerpt from TestCase class which extends PHPUnit_Framework_TestCase and is locate under app/tests directory.
Again, in order this to work, we have to create new testing directory and place all out settings inside. One gotcha when migrating database table for testing purposes is to forgot to tell Laravel the type of env we want that table to be used for. If don't, Laravel will be using default environmet. 
To choose right type of env it is enough to add --env="testing" at the end of migration command like this:

php artisan migrate --env="testing"

It can be used for local/development purposes also.
php artisan migrate --env="local"

Thanks for reading.

No comments:

Post a Comment