Question

We're are developing multiple applications based on Laravel 4. These applications run on the same webserver.

The Laravel4 environment detection is based on the hostname which sucks because we have multiple applications on the same machine. We created a work-around in the detection area so that it will set the environment based on the url.

We run the artisan --env=my_env migrate command when we update the applications DB. The problem is in the seeding, the seeding command doesn't have a env option so it will try to seed the db based on the hostname wich will not be correct.

I'm trying all day to find a solution but I can't find any on the Internet and my attempts to build a new command is just taking too much time and energy.

Does someone knows how to set the environment when seeding?

PS: I run the commands on the server through Grunt and I know the environment -inject it into the command-.

Was it helpful?

Solution 2

I thought about the situation some days and got to the conclusion that what we're trying to do isn't the correct way.

The correct way would be that every application has his own config files -with the different envs-. This way the resolve function of Laravel works fine. The situation now is that we have multiple clients within one application and strore does -clients- configuration files within one application. In this case the hostname resolve will return the one client's -every time the same client- config beacuse the clients applications run on the same machine.

Our solution We are going to write a deployment script for the different clients so that every client has his own application with their configs only (copy application, copy/overwrite client config into app).

Work-around The answer of @Antonio Carlos Ribeiro works offcourse but had to much impact on our application. We use the different environments and with this solution we had to use the same user/pass info on all environments or provide a different .environment file.

I wrote an Artisan command to make our deployment work for the moment. This command can seed a database with the configuration of the provided environment (php artisan db:seed_env my_env).

use Illuminate\Console\Command;
use Illuminate\Config\Repository;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;

class SeedEnvironmentDb extends Command {

    /**
     * The console command name.
     *
     * @var string
     */
    protected $name = 'db:seed_env';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Seed a database with the configuration of the environment';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function fire()
    {
        $cmd = $this;
        $app = App::make('app');

        // force the environment to the given one.
        $env = $app->detectEnvironment(function() use ($cmd) {
            return $cmd->argument('environment');
        });

        // create new config with the correct environment and overwrite the current one.
        $app->instance('config', $config = new Repository(
            $app->getConfigLoader(), $env
        ));

        // trigger the db seed (now with the correct environment)
        $this->call('db:seed');
    }

    /**
     * Get the console command arguments.
     *
     * @return array
     */
    protected function getArguments()
    {
        return array(
            array('environment', InputArgument::REQUIRED, 'The environment to seed.'),
        );
    }

    /**
     * Get the console command options.
     *
     * @return array
     */
    protected function getOptions()
    {
        return array();
    }

}

OTHER TIPS

You pointed it very well, Laravel environment guessing sucks the way we use to use it, but you can change that:

This is how I do set my environment flawlessly, so I don't have to deal with hostnames and still don't get my local environment conflict with staging and production.

Create a .environment file in the root of your application and define your environment and add your sensitive information to it:

<?php

return array(

     'APPLICATION_ENV' => 'development', /// this is where you will set your environment

     'DB_HOST' => 'localhost',
     'DB_DATABASE_NAME' => 'laraveldatabase',
     'DB_DATABASE_USER' => 'laraveluser',
     'DB_DATABASE_PASSWORD' => '!Bassw0rT',

);

Add it to your .gitignore file, so you don't risk having your passwords sent to Github or any other of your servers.

Right before $app->detectEnvironment, in the file bootstrap/start.php, load your .environment file to PHP environment:

foreach(require __DIR__.'/../.environment' as $key => $value) 
{
    putenv(sprintf('%s=%s', $key, $value));
}

And then you just have to use it:

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

    return getenv('APPLICATION_ENV'); // your environment name is in that file!

});

And it will work everywhere, so you don't need to have separate dirs for development and production anymore:

<?php

return array(

    'connections' => array(

         'postgresql' => array(
              'driver'   => 'pgsql',
              'host'     => getenv('DB_HOST'),
              'database' => getenv('DB_DATABASE_NAME'),
              'username' => getenv('DB_DATABASE_USER'),
              'password' => getenv('DB_DATABASE_PASSWORD'),
              'charset'  => 'utf8',
              'prefix'   => '',
              'schema'   => 'public',
         ),

    ),

);

Note that I don't set a fallback:

return getenv('APPLICATION_ENV') ?: 'local';

Because I want it to fail on every server I deploy my app to, to never forget configuring my environment on them.

Then you just have to select the environment in your DatabaseSeeder class:

public function run()
{
    if( App::environment() === 'development' )
    {
        $this->call('UserTableSeeder');
    } 
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top