关于WAMP环境下的多线程环境问题


在windows下配置了一套WAMP环境来跑Laravel。发现存在共享“.env”加载的变量污染问题。

下面说下这种情况:
使用两个Laravel项目,一个域名为user.xxx.com;另一个域名为test.xxx.com。
user.xxx.com的.env中的DB_DATABASE设为proj_user数据库,而test.xxx.com的DB_DATABASE设为proj_test数据库。
在user.xxx.com中提供一个获取用户信息的接口,而test.xxx.com项目中用CURL去请求user.xxx.com中的接口。

然后发现user.xxx.com获取用户信息的时候居然使用了proj_test数据库!!!!!!!

之后经过调试发现,在DotEnv项目中(<project dir>/vendor/vlucas/phpdotenv/src/Loader.php),下面的代码是设置环境变量的:

public function setEnvironmentVariable($name, $value = null)
    {
        list($name, $value) = $this->normaliseEnvironmentVariable($name, $value);

        // Don't overwrite existing environment variables if we're immutable
        // Ruby's dotenv does this with `ENV[key] ||= value`.
        if ($this->immutable && $this->getEnvironmentVariable($name) !== null) {
            return;
        }

        // If PHP is running as an Apache module and an existing
        // Apache environment variable exists, overwrite it
        if (function_exists('apache_getenv') && function_exists('apache_setenv') && apache_getenv($name)) {
            apache_setenv($name, $value);
        }

        if (function_exists('putenv')) {
            putenv("$name=$value");
        }

        $_ENV[$name] = $value;
        $_SERVER[$name] = $value;
    }

但是在if ($this->immutable && $this->getEnvironmentVariable($name) !== null)这句代码中,返回了true。也就是说在设置DB_DATABASE之前就已经存在这个配置了。继续调试后发现getEnvironmentVariable函数中的$value = getenv($name);这句代码返回了DB_DATABASE的值,并且是test.xxx.com的.env中的proj_test。

而我单独去访问user.xxx.com(也就是不通过test.xxx.com来去请求)的时候,却又读取了正确的数据库(proj_user)。

初步判断这个问题应该是test.xxx.com收到请求之后,读取.env并设置环境变量,而因为apache在windows下是以多线程模式运行的;在请求test.xxx.com的线程还没有退出的情况下.env加载的环境变量没有被释放,这时用CURL去请求user.xxx.com的时候就会在同一个进程空间里面读取到test.xxx.com的配置,上面那段设置变量的代码已经明显的说明如果读取到有这个配置,那么就直接return,不再重新加载,所以才会导致user.xxx.com自己的.env没有加载进来。

目前我用的解决方法是用php artisan config:cache命令来发布配置,这样就不会去读.env了。

不知道大家有没有什么更好的解决方案?毕竟在开发环境中每改一次config就要发布一次挺蛋疼的。


点赞 取消点赞 收藏 取消收藏

<< 上一篇: lumen 跨域请求 返回数据出现的问题

>> 下一篇: laravel5.2自带RBAC