Laravel多租户工作

时间:2017-06-19 20:39:48

标签: php laravel laravel-5 multi-tenant

遇到无法连接到数据库的问题。

Invalid catalog name: 1046 No database selected

我需要在作业中设置帐户,因此我有一个扩展类,以确保帐户随作业一起发送,以便我可以确保数据库可以连接到正确的数据库。

<?php

namespace App\Jobs;

use Illuminate\Support\Facades\DB;

abstract class Job
{
    protected $account;

    public function start()
    {
        // runs when creating the job, so the config holds the correct value
        $this->account = config('database.connections.tenant.database');
    }

    public function handle()
    {
        // since the handle function runs outside of setting the job 
        // the database is no longer set in the config
        config()->set('database.connections.tenant.database', $this->account);
        // try to force it to reconnect incase it already did for some reason.
        DB::reconnect();
    }
}

这是我正在玩的当前版本,变化似乎不会影响它。我基本上在构造函数中运行start,然后确保它在作业中运行父handle,以便它引导正确的数据库配置。

我正在寻找的最终结果是将租户数据库设置为account,当它运行作业时,它会使用该数据库进行所有查询。

1 个答案:

答案 0 :(得分:0)

找到解决这个问题的方法。它不漂亮,但基于我可以看到的laravels队列只是没有真正处理这种事情。

首先,我删除了handle函数的覆盖,我真正需要的是确保在Job类上提供运行所需队列的帐户。

abstract class Job
{
    protected $account;

    public function start()
    {
        // runs when creating the job, so the config holds the correct value
        $this->account = config('database.connections.tenant.database');
    }
}

接下来,我将切换到正确的租户数据库,转移到AppServiceProvider方法中的boot

Event::listen(JobProcessing::class, function ($event) {
   if ($payload = $event->job->payload()) {
      preg_match('/"account";s:[0-9]+:"(.*?)"/', $payload['data']['command'], $matches);
      if (count($matches)) {
         if (isset($matches[1])) {
            config()->set('database.connections.tenant.database', $matches[1]);
            config()->set('database.default', 'tenant');
         }
      }
   }
});

我在这里做的是查看具有一些正则表达式的帐户的序列化对象。可能会在这里进行改进,但到目前为止在测试中都有效。然后,一旦确认帐户,它就会设置正确的数据库。

我必须走这么远的原因是Job在作业本身被序列化时会进行查询,所以为了通过帐户,它需要在序列化之前完成。