Gabriel
Gabriel

Reputation: 441

Weird Laravel 5 caching using wrong database name

I have two Laravel APIs that are serving an AngularJS app all on my local development machine. I'm getting a weird issue when the Angular page calls POSTs to both APIs where it seems to be using the wrong database name (it's using the other Laravel's instance's database). Laravel throws an exception that says Table database.table not found, where database is the incorrect database. I've tried calling each of the APIs using Postman and that works fine, and I'm sure there is no mention of the other database in either project.

To me this seems like a caching issue, where the .env file might be cached and shared between the two Laravel servers for some reason. Both of the Laravel apps are hosted on Apache. I've tried calling php artisan config:clear and have set the appropriate headers in the .htaccess files to try to prevent any caching but neither of those worked. I have also tried on multiple browsers, cleared the cache, and still the same error.

I want to be able to use the .env file so that I can have a unique configuration for my development server so I'd rather not hardcode the database credentials in config/database.php. Any ideas what could be the issue?

Both database.php files look like:

'mysql' => [
'driver'    => 'mysql',
'host'      => env('DB_HOST'),
'database'  => env('DB_DATABASE'),
'username'  => env('DB_USERNAME'),
'password'  => env('DB_PASSWORD'),
'charset'   => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix'    => '',
'strict'    => false, 
],

Where the unique settings are stored in .env

Upvotes: 12

Views: 29309

Answers (9)

Jk33
Jk33

Reputation: 905

I was also getting some random Unknown database 'dbname' errors, the name that was logged did not match with the actual name in the .env file.

None of the answers worked for me, but restarting the whole server did work.

Upvotes: 0

baxter
baxter

Reputation: 1

You could force the command returning this error to use the env file by adding --env = productionif you want to use .env.production

Upvotes: 0

user11436097
user11436097

Reputation: 43

What works for me, without additional actions is just to clear the cache and restart Apache2:

php artisan config:cache
sudo /etc/init.d/apache2 restart

Upvotes: 0

SuperNOVA
SuperNOVA

Reputation: 751

If anyone is still having this issue, like I was. Then you can use the command:

php artisan config:cache

after setting the environment as mentioned here.

The problem now is that whenever a team member changes something in an environment file of any product, this command should surely run.

Upvotes: 21

Dali
Dali

Reputation: 7882

A server restart with php artisan serve have fixed the same problem for me

Upvotes: 6

ssssteve
ssssteve

Reputation: 79

Old question, but just in case anyone else finds this is happening to them (as has just happened to me) my simple solution was to change the names of the .env variables in one of the projects:

DB_X_HOST="localhost"
DB_X_DATABASE="other_project"
DB_X_USERNAME="homestead"
DB_X_PASSWORD="secret"
DB_X_PORT="3306"

You then change the variables in config\database.php to read:

'mysql' => [
        'driver' => 'mysql',
        'host' => env('DB_X_HOST', '127.0.0.1'),
        'port' => env('DB_X_PORT', '3306'),
        'database' => env('DB_X_DATABASE', 'forge'),
        'username' => env('DB_X_USERNAME', 'forge'),
        'password' => env('DB_X_PASSWORD', ''),
        'charset' => 'utf8mb4',
        'collation' => 'utf8mb4_unicode_ci',
        'prefix' => '',
        'strict' => true,
        'engine' => null,
    ]

Now you shouldn't have the cross contamination detailed in Mark's response

Upvotes: 7

Denis Priebe
Denis Priebe

Reputation: 2855

What worked for me was to clear a bunch of the Laravel settings by running these commands:

php artisan config:clear
php artisan cache:clear
php artisan route:clear
php artisan view:clear
php artisan optimize

I'm not sure which command did it, but Laravel now recognizes/reads the .env file correctly for my database configuration.

Upvotes: 23

Mark Leong
Mark Leong

Reputation: 1528

I experienced the same problem and in my case it was caused by the issue reported by toddbc on https://github.com/vlucas/phpdotenv/issues/76.

Laravel relies on vlucas/phpdotenv, which uses PHP's putenv() to add values from the .env file so that they are accessible to your application. However,

putenv() and getenv() are not required to be re-entrant or thread safe. What this means is that if two threads happen to call them at the same time (either on different cores, or from a context switch in the middle of the function), bad things can happen.

Thus, two instances of PHP (in my case from different applications) were able to read the environment variables belonging to each other during concurrrent requests.

As vlucas helpfully explains in his reply to the issue report, this is expected behavior and the solution is to define your environment variables in your webserver config file.

What worked for me was to remove the DB_HOST, DB_DATABASE, DB_USERNAME, DB_PASSWORD lines from my .env file and add the following to my Apache vhost config block:

SetEnv DB_HOST db_host
SetEnv DB_DATABASE db_name
SetEnv DB_USERNAME db_user
SetEnv DB_PASSWORD db_pass

(Don't forget to restart Apache after changing the config)

Note that if you have one Laravel app in your web root and an additional Laravel app installed in a subdirectory that uses the Apache Alias directive to route requests to the right application, you will need to use SetEnvIf for BOTH sets of database credentials, like so:

# Laravel app 1 in web root
SetEnvIf Host ".*" DB_HOST=db1_host
SetEnvIf Host ".*" DB_DATABASE=db1_name
SetEnvIf Host ".*" DB_USERNAME=db1_user
SetEnvIf Host ".*" DB_PASSWORD=db1_pass

# Laravel app 2 in subdirectory "/subdir"
SetEnvIf Request_URI ^/subdir DB_HOST=db2_host
SetEnvIf Request_URI ^/subdir DB_DATABASE=db2_name
SetEnvIf Request_URI ^/subdir DB_USERNAME=db2_user
SetEnvIf Request_URI ^/subdir DB_PASSWORD=db2_pass

(For an explanation of why you can't use a combination of SetEnv and SetEnvIf, see https://staff.washington.edu/fmf/2013/04/24/using-setenv-and-setenvif-together-in-apache/)

The nice thing about this solution (if it works for you) is that it only needs to be implemented in the environments where the problem manifests i.e. if it only affects your local dev environment, then nothing needs to be changed on your production server.

Upvotes: 7

David Carr
David Carr

Reputation: 49

I have the exact same problem. One web page will request 5 json responses with different data sets from laravel and about half of the requests will bomb with an 'incorrect database' error even though when you reload those exact requests in their own browser tab they work fine. Seems like a Laravel bug having to do with handling simultaneous web requests from apache.

Anyway, my workaround was to hard-code the host, db, username, and password for all connections in my config\database.php file and now my json requests don't bomb anymore. It sucks, however, to have to hard-code passwords into source control and deal with multiple environments - essentially going back to the dark ages before .env files existed.

Upvotes: 0

Related Questions