如何在laravel 5中覆盖失败的作业插入的数据库连接?

Roh*_*han 5 php queue laravel laravel-5

我正在尝试开发一个多租户多数据库应用程序,这基本上意味着每个租户都有自己的数据库、自己的用户、资源等。

当然,当请求进来时,Laravel 需要知道要使用哪个 DB 连接,所以我编写了一个中间件,它基本上解析请求中的 JWT 并查找租户 ID 或用户名,然后简单地连接到租户的数据库。

但是现在我正在使用队列,并且我试图超越连接到主数据库并插入失败作业记录的 laravel 5 的默认行为。

当我深入研究供应商文件时,我发现了一个FailedJobProvider接口:

<?php

namespace Illuminate\Queue\Failed;

interface FailedJobProviderInterface
{
    /**
     * Log a failed job into storage.
     *
     * @param  string  $connection
     * @param  string  $queue
     * @param  string  $payload
     * @return void
     */
    public function log($connection, $queue, $payload);

    /**
     * Get a list of all of the failed jobs.
     *
     * @return array
     */
    public function all();

    /**
     * Get a single failed job.
     *
     * @param  mixed  $id
     * @return array
     */
    public function find($id);

    /**
     * Delete a single failed job from storage.
     *
     * @param  mixed  $id
     * @return bool
     */
    public function forget($id);

    /**
     * Flush all of the failed jobs from storage.
     *
     * @return void
     */
    public function flush();
}
Run Code Online (Sandbox Code Playgroud)

还有一个实现该接口的DatabaseFailedJobProvider类:

<?php

namespace Illuminate\Queue\Failed;

use Carbon\Carbon;
use Illuminate\Database\ConnectionResolverInterface;

class DatabaseFailedJobProvider implements FailedJobProviderInterface
{
    /**
     * The connection resolver implementation.
     *
     * @var \Illuminate\Database\ConnectionResolverInterface
     */
    protected $resolver;

    /**
     * The database connection name.
     *
     * @var string
     */
    protected $database;

    /**
     * The database table.
     *
     * @var string
     */
    protected $table;

    /**
     * Create a new database failed job provider.
     *
     * @param  \Illuminate\Database\ConnectionResolverInterface  $resolver
     * @param  string  $database
     * @param  string  $table
     * @return void
     */
    public function __construct(ConnectionResolverInterface $resolver, $database, $table)
    {
        $this->table = $table;
        $this->resolver = $resolver;
        $this->database = $database;
    }

    /**
     * Log a failed job into storage.
     *
     * @param  string  $connection
     * @param  string  $queue
     * @param  string  $payload
     * @return void
     */
    public function log($connection, $queue, $payload)
    {
        $failed_at = Carbon::now();

        $this->getTable()->insert(compact('connection', 'queue', 'payload', 'failed_at'));
    }

    /**
     * Get a list of all of the failed jobs.
     *
     * @return array
     */
    public function all()
    {
        return $this->getTable()->orderBy('id', 'desc')->get();
    }

    /**
     * Get a single failed job.
     *
     * @param  mixed  $id
     * @return array
     */
    public function find($id)
    {
        return $this->getTable()->find($id);
    }

    /**
     * Delete a single failed job from storage.
     *
     * @param  mixed  $id
     * @return bool
     */
    public function forget($id)
    {
        return $this->getTable()->where('id', $id)->delete() > 0;
    }

    /**
     * Flush all of the failed jobs from storage.
     *
     * @return void
     */
    public function flush()
    {
        $this->getTable()->delete();
    }

    /**
     * Get a new query builder instance for the table.
     *
     * @return \Illuminate\Database\Query\Builder
     */
    protected function getTable()
    {
        return $this->resolver->connection($this->database)->table($this->table);
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我想如果我编写自己的提供程序或者可以超越这个提供程序,我将能够在插入失败的作业之前告诉 laravel 连接到哪个数据库。但是我对 SOLID 或 OOP 不太熟悉,并且对在这种情况下该怎么做感到困惑。

如何编写我自己的提供程序或超越此提供程序以随时随地更改数据库连接?

abe*_*ree 4

我知道这已经太晚了,但我遇到了同样的问题。我想到了。因此,对于遇到此问题的其他人来说,这是这样做的:

首先,您需要创建自己的失败作业提供者类来实现该FailedJobProviderInterface接口。我建议将代码复制Illuminate\Queue\Failed\DatabaseFailedJobProvider到您的自定义类中,然后简单地将其更改为您需要的工作方式。Laravel 使用此类中的其余函数执行多项操作,并且类本身需要与实现的接口相匹配。

我只是更改了日志方法,将附加数据记录到数据库中的附加列中。

一旦完成,在服务提供商(您自己的或默认的)中,您需要包含您刚刚创建的新的失败作业提供商类。

然后在服务提供者的boot方法中放入以下代码:

// Get a default implementation to trigger a deferred binding
$_ = $this->app['queue.failer'];

//regiter the custom class you created
$this->app->singleton('queue.failer', function ($app) {

    $config = $app['config']['queue.failed'];
    return new NAMEOFYOURCLASS($app['db'], $config['database'], $config['table']);

});
Run Code Online (Sandbox Code Playgroud)

该代码将覆盖Laravel 完成的注册

为了代码清晰起见,您可以将该代码作为函数放入服务提供程序中,并在启动方法中运行该方法。

如果您想将不同的数据记录到数据库中,请确保同时更新失败的作业迁移和/或数据库表。

现在,当作业失败时,您的自定义代码将按照您的意愿运行记录失败的作业,即使您更新了 Laravel 版本,这也应该可以正常工作。