当从另一个Laravel应用程序发送Http请求时,Laravel使用错误的数据库

q5lcpyga  于 2023-03-04  发布在  其他
关注(0)|答案(3)|浏览(88)

我似乎遇到了一个奇怪的问题。我使用Http facade触发了一个从一个laravel应用到另一个laravel应用的post请求。这两个应用都链接到不同的数据库。当我尝试使用postman触发同一个端点时,它工作正常,但当请求从另一个laravel应用触发时,接收方laravel应用尝试使用发送方应用的数据库设置,但该设置不起作用。我当前使用Windows上的Xampp托管这两个应用,并且软件包是最新版本。有人遇到过类似的问题吗?你能提出解决方案吗?
代码如下所示:发送POST请求的服务(发送方应用程序(1)):

Http::post("http://localhost/second_app/public/api/test", array(
                    'id' => 1,
);

接收请求的代码(接收器应用程序(2)):

public function test(Request $request)
{
    $club = Club::find($request->id);
}

我在日志文件中收到一个错误,指出它正在尝试查找first_app数据库中的clubs表,而实际上它应该使用second_app数据库。我尝试记录配置和请求。在此发布的请求相当大,但我已验证是否正确接收。此日志的代码为:

Log::info("Received Request", ['database' => ['driver' => config('database.default'), 'name' => config('database.connections.'.config('database.default').'.database')]]);

如果请求从Postman发送到second_app或从second_app发送到自身(使用Http facade)

[2021-08-17 03:13:56] local.INFO: Received Request {"database":{"driver":"mysql","name":"second_app"}}

如果使用Http外观将请求从first_app发送到second_app

[2021-08-17 03:14:01] local.INFO: Received Request {"database":{"driver":"mysql","name":"first_app"}} 
[2021-08-17 03:14:01] local.INFO: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'first_app.projects' doesn't exist (SQL: select * from `projects` where `code` = ABC_01 limit 1) {"exception":"[object] (Illuminate\\Database\\QueryException(code: 42S02): SQLSTATE[42S02]: Base table or view not found: 1146 Table 'first_app.projects' doesn't exist (SQL: select * from `projects` where `code` = ABC_01 limit 1) at \\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Connection.php:692)

应用程序的配置与默认设置相同。. env文件中填充了以下详细信息

#first_app
DB_DATABASE="first_app"

#second_app
DB_DATABASE="second_app"
    • UPDATE**我也尝试使用单独的vhosts。firstapp.testsecondapp.test已设置,文档根目录指向公共目录。问题仍然存在,从first_app发送请求时使用了不正确的配置,但从second_app或Postman内部发送请求时,该配置工作正常(如前所述)
ohfgkhjo

ohfgkhjo1#

我尝试在接收方应用中硬编码database.php配置值,而不是使用env helper,这解决了问题。看起来env helper在接收方应用中使用发送方应用的环境变量导致了冲突。

vq8itlhq

vq8itlhq2#

我也有同样的问题。
并且我通过使用php artisan optimize缓存所有配置来修复它。
硬编码数据库配置也可以

vxqlmq5t

vxqlmq5t3#

    • 原因**

Laravel使用vlucas/phpdotenv来管理环境变量,phpdotenv从$_ENV$_SERVER以及可选的php的getenv()putenv()中存储/检索变量。
vlucas/phpdotenv不鼓励使用getenv()putenv(),因为它"不是线程安全的"。这两个php方法将环境变量附加到进程,而不是线程/请求。Windows上的Apache使用mod_php作为php处理程序,在一个进程下运行多个虚拟主机,正如广泛讨论的here
默认情况下,Laravel启用phpdotenv库中的putenv适配器。
所以现在的情况是:
1.第一个Laravel站点通过Env facade使用putenv()设置环境变量。
1.第一个Laravel站点在同一进程中对作为虚拟主机运行在同一服务器上的第二个Laravel站点进行API调用。
1.第二个站点看到DB_DATABASE已经通过读取getenv('DB_DATABASE')进行了配置,因此读取该值,因为put/getenv()是进程级的。

  1. SQL查询处理器尝试连接到错误的数据库。
    • 解决方案**

告诉Laravel禁用PutenvAdapter env适配器。将以下行添加到bootstrap/app.php中。Laravel将回退到使用线程安全的$_ SERVER和$_ ENV。

\Illuminate\Support\Env::disablePutenv();

要将范围限制为Windows + Apache + mod_php,请使用以下代码。我还没有测试Linux构建的Apache是否会受到putenv虚拟主机交叉污染。

if(php_sapi_name() === 'apache2handler' && ($_SERVER['WINDIR'] ?? false)) {
    \Illuminate\Support\Env::disablePutenv();
}
    • 风险**

禁用PutenvAdapter确实限制了Laravel可以检索环境变量的位置。如果您以不寻常的方式设置环境变量,请确保彻底测试您的应用程序。

相关问题