Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 507
Gabriel Avatar asked Sep 30 '15 21:09

Gabriel


4 Answers

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.

like image 163
Denis Priebe Avatar answered Nov 06 '22 02:11

Denis Priebe


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.

like image 19
SuperNOVA Avatar answered Nov 06 '22 00:11

SuperNOVA


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.

like image 7
Mark Leong Avatar answered Nov 06 '22 01:11

Mark Leong


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

like image 7
ssssteve Avatar answered Nov 06 '22 02:11

ssssteve