laravel enviroment when on command line different

2019-08-02 08:19发布

问题:

I have deployed my laravel app to an elastic beanstalk enviroment. This app detects its environment with this piece of code in bootstrap/start.php

$env = $app->detectEnvironment(function () {
    return getenv('APP_ENV') ?: 'local';
});

When elastic beanstalk starts it runs its configuration files which I have set up to detect if a parameter is set. in this case I have set this parameter to development and the configuration files then set enviroment variables based on this namely

APP_ENV = development
DB_HOST = rds dev endpoint
DB_NAME = rds dev db name
DB_USERNAME = dev username
DB_PASSWORD = devdb pass

When I visit the app in the browser it is working as intended and it is correctly connecting to the dev db.

When I ssh into the server and try to run

php artisan migrate

I get a pdo exception no such file or directory

when I run

php artisan env

local is returned even though the environment variable APP_ENV is defined. I am doubly sure that this variable is defined because when laravel errors in the browser I can see the variable with the value development in the server/request data along with the other environment variables that are created on environment launch

what am I missing?

edited to include personalised solution based on antonios answer

.environment

<?php
if (getenv('PARAM1') === false) {
    return false;
} else {
    switch (getenv('PARAM1')) {
        case 'development':

            return array(
                'APP_ENV' => 'development',

                'DB_HOST' => '***',
                'DB_NAME' => '***',
                'DB_USERNAME' => '***',
                'DB_PASSWORD' => '***',
                );
            break;

        case 'staging':

            return array(
                'APP_ENV' => 'staging',

                'DB_HOST' => '***',
                'DB_NAME' => '***',
                'DB_USERNAME' => '***',
                'DB_PASSWORD' => '***',
                );
            break;

        case 'production':

            return array(
                'APP_ENV' => 'production',

                'DB_HOST' => '***',
                'DB_NAME' => '***',
                'DB_USERNAME' => '***',
                'DB_PASSWORD' => '***',
                );
            break;
    }
}

start.php

$env = require __DIR__.'/../.environment';

if ($env !== false) {
    foreach ($env as $key => $value) {
        putenv(sprintf('%s=%s', $key, $value));
    }
}

$env = $app->detectEnvironment(function () {
    return getenv('APP_ENV') ?: 'local';
});

回答1:

When you run

php artisan migrate

php runs under a different user, not your web server, so you need to:

php artisan migrate --env=development

EDIT

Having trouble with cli and web is one of the reasons why I don't use those web servers env vars. This is how I do my environments:

Create a .environment file in the root of your application and define your environment:

<?php

return array(

     'APP_ENV' => 'development',

     'POSTGRESQL.HOST' => 'localhost',
     'POSTGRESQL.DATABASE_NAME' => 'laraveldatabase',
     'POSTGRESQL.DATABASE_USER' => 'laraveluser',
     'POSTGRESQL.DATABASE_PASSWORD' => '!Bassw0rT',

);

Add it to your .gitignore application file, so you don't risk having your passwords sent to Github.

Right before $app->detectEnvironment, load the .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('APP_ENV');
});

It will work everywhere:

<?php

return array(

    'connections' => array(

         'postgresql' => array(
              'driver'   => 'pgsql',
              'host'     => getenv('POSTGRESQL.HOST'),
              'database' => getenv('POSTGRESQL.DATABASE_NAME'),
              'username' => getenv('POSTGRESQL.DATABASE_USER'),
              'password' => getenv('POSTGRESQL.DATABASE_PASSWORD'),
              'charset'  => 'utf8',
              'prefix'   => '',
              'schema'   => 'public',
         ),

    ),

);

Note that I don't do

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

Because I want it to fail on every server I deploy my app to.