6

Laravel 4.1 removed the feature to use the domain for detecting what environment the app is running in. Reading the docs they now suggest using host names. However, to me that seems cumbersome if you are working in a team. Should everyone change the bootstrap/start.php file and add their own host name to be able to run the app in a dev environment? Also, what if you want to have two different environments on the same machine?

How to best detect the environment if you are working in a team in Laravel 4.1+?

Simon Bengtsson
  • 7,573
  • 3
  • 58
  • 87

8 Answers8

14

Here is my settings from bootstrap/start.php file:

$env = $app->detectEnvironment(function() use($app) {
    return getenv('ENV') ?: ($app->runningInConsole() ? 'local' : 'production');
});

Instead of default array, this method in my case is returning closure with ternary. That way I got more flexibility in choosing desired environment. You can use switch statement also. Laravel will read return value and configure itself. With getenv native function, I am just listening for a given environment. If my app is on the server, then it will "pick" server configurations. If locally, then it will pick local (or development) And don't forget to create custom directories for you environemnts in app/config There is also testing env, which is choosen automatically, every time you are unit testing app.

Laravel makes working with environments really fun.

UPDATE:

With environments we are mostly cencerned about db credentials.

For production I use Fortrabbit, so when configuring new app on server, fortrabbit is generating those values for me. I just need to declare them. e.g. DB of just database or db... Or DB_HOST or HOST ... Locally, those values are the one you use for your localhost/mysql settings.

leek
  • 11,803
  • 8
  • 45
  • 61
Miroslav Trninic
  • 3,327
  • 4
  • 28
  • 51
  • That looks beautiful! I didn't have the "ENV" variable though. I suppose you have to set it in the apache config somewhere? Do you mind adding instructions for that in your answer? – Simon Bengtsson Feb 12 '14 at 14:47
  • Inspired by your answer I read the docs again and found they are actually suggesting something very similar as well, but using $_SERVER['ENV'] instead of getenv('ENV'). http://laravel.com/docs/configuration#environment-configuration – Simon Bengtsson Feb 12 '14 at 14:53
  • 1
    I guess getenv("ENV") is pointing to $_SERVER["ENV"]. So use what works. And please accept answer if you like it. – Miroslav Trninic Feb 12 '14 at 14:58
  • I didn't really get your update. You never set the "ENV" variable? Not even locally? By the way, Fortrabbit looks great. – Simon Bengtsson Feb 12 '14 at 15:04
  • Hey Simon - let me clarify to you. I did set "ENV" variable - it is called "local" or "development" or whatever.In Laravel env variable is the name of the folder in which you will place you environment settings. That folder should be placed inside app/config/ directory. Laravel will read content of that folder. Default environment is production, and Laravel reads everything what is inside app/config/. So you just "steal" some settings, place them under new directory and tell laravel in bootstrap/start.php what is the name of you new environment name. Clear ? – Miroslav Trninic Feb 12 '14 at 16:25
  • Sure, thanks! I do use special config folders depending on the environment that the app is currently running in, however so far I found them pretty limited. Most of my config is kept out of version control and placed in the *env-name*.env.php files in the root folder. – Simon Bengtsson Feb 12 '14 at 19:17
  • 1
    What I was looking for was where to set this ENV variable. You can do it in apache's virtual server conf: http://stackoverflow.com/questions/10902433/setting-environment-variables-for-accessing-in-php – Aurelien May 24 '14 at 08:16
  • For NGINX you can set ENV by adding `fastcgi_param ENV production; ` to `location ~ \.php$ {` in the vhost. – DutGRIFF Aug 25 '14 at 22:33
3

Update:

In Laravel 5.0 environment detection is no longer needed in the same way. In the .env file you can simply have a variable for which environment the app should run in.

Old answer for Laravel <= 4.2

What I ended up doing is very close to what carousel suggested. Anyway, thought I would share it. Here is the relevant part of our bootstrap/start.php file:

$env = $app->detectEnvironment(function ()
{
    if($app->runningInConsole())
        return "development";

    $validEnvironments = array("development", "staging", "production");
    if (in_array(getenv('APP_ENV'), $validEnvironments)) {
        return getenv('APP_ENV');
    }
    throw new Exception("Environment variable not set or is not valid. See developer manual for further information.");
});

This way all team members have to declare an environment variable somewhere. I haven't really decided if throwing an exception if the environment variable is not set or just default to production is the best thing. However, with the above, it's easy to change.

Simon Bengtsson
  • 7,573
  • 3
  • 58
  • 87
  • This doesn't work when using the command line. Carousel's answer takes `$app->runningInConsole()` into consideration and uses `local`. This allows you to run `php artisan`. With your way I don't think you can. – Dustin Griffith Aug 25 '14 at 22:19
  • You can actually specify the environment with the `artisan --env` switch. However, I agree that Carousel's solution is better. Updated the answer. – Simon Bengtsson Aug 25 '14 at 22:30
1

For me, I just use 'dev' => '*.local' and it works. I haven't 100% tested in a team situation but I think it'd work (big assumption alert:) assuming you're on OSX and get the default Alexs-iMac.local-like hostname.

As for faking an environment, I'm not sure it's really supported. It'll be doable, but in general the whole point of environments is that dev has entirely different needs to production and the two are mutually exclusive. Having the ability to switch on one physical environment seems counter to that goal.

alexrussell
  • 13,856
  • 5
  • 38
  • 49
  • I don't think that will work on all platforms. I have windows and my current host name is "hhp" – Simon Bengtsson Feb 12 '14 at 14:59
  • I certainly concede that point. You could try seeing if the detectEnvironment array can cascade though. Set prod first, then `'dev' => '*'` or something. That said, you've accepted using environment variables answer so I'll leave quietly now :) – alexrussell Feb 12 '14 at 15:05
  • What do you mean by cascade? – Simon Bengtsson Feb 12 '14 at 15:07
  • Well I don't think I actually mean cascade so much as do later rules override previous rules? So like I said, if you had `['prod' => 'servername.com', 'dev' => '*']` then does it work as expected and correctly see prod on prod and everything else as dev or does it work the other way around? Worth looking into anyway. – alexrussell Feb 12 '14 at 15:15
  • Ah! That might work. However, there might be security issues having the dev environment as default. – Simon Bengtsson Feb 12 '14 at 15:18
  • Very true. That said, the answer you accepted does the same thing. Of course, if you know all your teams' hostnames, you can do `'dev' => ['hhp', 'Alexs-iMac.local', '...']` – alexrussell Feb 12 '14 at 15:19
  • Yeah I suppose. Would be nice to be able to avoid having to constantly change that file though as other people joins or if new computers is bought/used. I will add another answer soon with what I ended up doing, very close to the accepted however. – Simon Bengtsson Feb 12 '14 at 16:04
1

Laravel 4.1 and 4.2 detects the environments through the machine names specified in the "bootstrap/start.php" file.

For example, in my case the config becomes:

$env = $app->detectEnvironment(array(
  'local' => array('Victor.local', 'Victor-PC'),
));

This means that Laravel will use the 'local' environment settings for both machines: 'Victor.local' (a Mac) and 'Victor-PC' (Windows).

This way you can regsiter several machines to work as local environment. Other environments can be registered too.

In order to know the current machine name, you can use the following PHP code:

<?php echo gethostname(); ?>

Hope it helps!

Victor BV
  • 1,051
  • 13
  • 9
0

You can use something like this:

$env = $app->detectEnvironment(function(){
    if($_SERVER['HTTP_HOST'] == 'youdomain_local')
    {
        return 'local';
    }elseif($_SERVER['HTTP_HOST'] == 'youdomain_team')
    {
        return 'team';
    }else{
        return 'production';
    }
});
Simon Bengtsson
  • 7,573
  • 3
  • 58
  • 87
Tấn Tâm
  • 130
  • 4
0

what i did is, make dir app/config/local and use code

$env = $app->detectEnvironment(function(){
    return $_SERVER['HTTP_HOST']=="localhost"?"local":"production";
});

For localhost and online.

Wasim A.
  • 9,660
  • 22
  • 90
  • 120
  • This is very easy to 'hack'. You can try it yourself by redirecting localhost to your live domain in your hosts file. That would make it possible to run your live site in 'local' mode which in turn might make it possible to see all your db config and passwords etc. – Simon Bengtsson Aug 06 '14 at 02:42
  • This throws an error for me when using the CLI (Artisan), as it can't access HTTP_HOST – Alias Sep 24 '14 at 10:35
0

I didn't like that production was default, so I made it anything other than live server will go to local configs:

in bootstrap/start.php :

$env = $app->detectEnvironment(function(){
    if (gethostname() !== 'live_server_hostname'){
        return 'local';
    } else {
        return 'production';
    }
});
shazbot
  • 565
  • 6
  • 14
0

In bootstrap/start.php define this:

$env = $app->detectEnvironment(function() use($app) {

    $enviromentsHosts = [
        'localhost',
        'local',
    ];

    if ($app->runningInConsole() || in_array($app['request']->getHost(), $enviromentsHosts)) {

        return 'local';

    } else {

        return 'production';
    }
});

I believe it is better to use only the resources of Laravel 4

Wallace Vizerra
  • 3,382
  • 2
  • 28
  • 29