You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel core请求Lumen log项目时误连core数据库导致表不存在报错

问题描述

我对Laravel并不陌生,但近期遇到了一个前所未见的异常问题。本地环境下部署了两个项目:基于Laravel开发的core项目,以及基于Lumen开发的log项目,业务逻辑为core向log推送数据,log负责将数据写入自身的数据库中。

core项目.env配置

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:rAfY+jMXkAsPz+wBrDksLNsPCLYzfNLI+FISLfqZ/1s=
APP_DEBUG=true
APP_URL=http://localhost/core

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=
DB_PORT=3306
DB_DATABASE=core
DB_USERNAME=root
DB_PASSWORD=

BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120

REDIS_HOST=localhost
REDIS_PASSWORD=
REDIS_PORT=6379
REDIS_EXPIRE=14400

MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

log项目.env配置

APP_NAME=Lumen
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost/log
APP_TIMEZONE=UTC

LOG_CHANNEL=stack
LOG_SLACK_WEBHOOK_URL=

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=log
DB_USERNAME=root
DB_PASSWORD=

CACHE_DRIVER=file
QUEUE_CONNECTION=sync

log项目Log模型定义

class Log extends Model
{
    protected $fillable = ['entity_type', 'entity_id', 'user_id', 'metadata', 'action'];
    protected $table = 'logs';
}

logs表迁移文件

class CreateLogsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('logs', function (Blueprint $table) {
            $table->id();
            $table->string('entity_type')->nullable();
            $table->unsignedBigInteger('entity_id')->nullable();
            $table->index(['entity_type', 'entity_id']);
            $table->unsignedBigInteger('user_id');
            $table->index('user_id');
            $table->text('metadata')->nullable();
            $table->enum('action', ['create', 'edit', 'delete', 'report']);
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('logs');
    }
}

log项目存储接口代码

public function store(Request $request)
{
    $validator = Validator::make($request->all(), [
        'metadata' => 'sometimes|json',
        'user_id' => 'required',
        'action' => 'required|in:create,edit,delete,report',
        'entity_id' => 'required',
        'entity_type' => 'required',
    ]);

    if ($validator->fails())
        return response()->json(['error' => true]);

    try {
        Log::create($request->all());
        return response()->json(['error' => false]);
    } catch (\Throwable $e) {
        return response()->json(['error' => $e->getMessage()]);
    }
}

core项目推送数据代码

static::updated(function (Model $model) {
    $data = [
        'entity_type' => self::$tableModelMapper[$model->getTable()],
        'entity_id' => $model->getAttribute('id'),
        'user_id' => optional(auth()->user())->id,
        'metadata' => json_encode($model->getDirty()),
        'action' => 'edit'
    ];

    $client = new Client();
    $client->post('http://localhost/log/public/store',
        [
            'json' => $data
        ]);
});

问题表现

  • 通过Postman向log接口推送以下格式的请求数据时,数据可正常写入log数据库的logs表中:
{
    "metadata":"{\"name\": \"Alex\",\"family\": \"Nicole\"}",
    "user_id": 1,
    "action": "create",
    "entity_id": 12,
    "entity_type":"Order"
}
  • 但通过core项目的上述代码推送请求时,返回如下报错:

Server error: POST http://localhost/log/public/store resulted in a 500 Internal Server Error response: <!-- SQLSTATE[42S02]: Base table or view not found: 1146 Table 'core.logs' doesn't exist (SQL: insert into logs (`en (truncated...)

报错显示程序尝试访问core数据库的logs表,但logs表实际位于log数据库中,且写入逻辑完全在log项目内部,不应该出现访问core数据库的情况。为定位问题,我在log项目的store方法中添加了如下调试代码:

$result = DB::connection()->getDatabaseName();
\Illuminate\Support\Facades\Log::info($result);

测试发现,Postman请求时日志输出的数据库名是log,而来自core的请求输出的数据库名是core,也就是说core发起请求时,log项目内部异常读取了core项目的数据库配置。


问题原因

核心原因是PHP-FPM进程的环境变量复用,加上Laravel/Lumen的Dotenv加载规则导致的配置覆盖:

  1. 本地两个项目共用同一套PHP-FPM进程池,FPM进程处理完core项目的请求后,不会主动清空进程内存储的环境变量,当同一个进程后续处理log项目的请求时,就会保留core项目的环境变量值。
  2. Laravel/Lumen默认使用的Dotenv加载逻辑是:如果对应的环境变量(比如DB_DATABASE、DB_HOST)已经在进程中存在,就不会再读取当前项目.env文件里的配置,直接复用已有的值,因此log项目就会拿到core项目的数据库配置。
  3. Postman请求正常的原因是测试时刚好分配到了没有处理过core项目请求的干净FPM进程,会正常加载log项目的.env配置,如果先访问一次core项目再用Postman请求log接口,同样会触发报错。
解决方案
  • 方案1:为两个项目配置独立的本地域名(比如core.test、log.test),同时为每个站点分配独立的FPM进程池,彻底隔离项目运行环境,从根源避免环境变量互相干扰。
  • 方案2:修改Dotenv加载逻辑,强制覆盖已存在的环境变量。Lumen项目可以修改bootstrap/app.php中的Dotenv加载代码,将默认的Dotenv::load改为Dotenv::overload;Laravel项目可以使用Dotenv::createUnsafeMutable方法加载.env文件,允许覆盖已有环境变量。
  • 方案3:本地开发时使用artisan serve启动两个项目,分别使用不同端口(比如core用8000,log用8001),这种方式每个项目是独立的PHP进程,不会出现环境变量复用的问题。

内容的提问来源于stack exchange,提问作者M a m a D

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 08:48:04