Laravel 队列数据未从构造函数传递到处理程序

Laravel queue data not being passed from constructor to handler

我遇到了 Laravel 5.6 排队作业的问题。我将 3 个参数传递给构造函数。此时,我检查了所有参数都有数据。但是当我 运行 作业时,其中一个在处理程序中是空的。

这是调度作业的函数:

public function send() {
    $event = Evento::find($id);
    $subscribers = ParticipantesEvento::join('users', 'participantes_eventos.user_id', '=', 'users.id')
           ->select('users.name', 'users.email')
           ->where('evento_id', '=', $evento->id)
           ->get();
    $certificate = Certificado::where('evento_id', '=', $evento->id)->first();

    dispatch(new SendCertificatesByEmail($subscribers, $event, $certificate));

    return redirect()->back()->with('success', 'Fazendo os paranauê...');
}

这是工作:

namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class SendCertificatesByEmail implements ShouldQueue {

    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $subscribers, $events, $certificate;

    public function __construct($s, $e, $c) {
        $this->subscribers = $s;
        $this->events      = $e;
        $this->certificate = $c;

        print_r($this->subscribers);   // Have data
        print_r($this->events);        // Have data
        print_r($this->certificate);   // Have data
    }

    public function handle() {
        print_r($this->subscribers);    // IS EMPTY!!!
        print_r($this->events);         // Have data
        print_r($this->certificate);    // Have data
    }
}

虽然 Laravel 的文档说要在作业中将变量声明为受保护的,但我也已经尝试将它们作为 public。同样的问题。我已经没主意了。我做错了什么??

您的 eloquent 个模型集合结构不正确。因此,Laravel 无法正确序列化它们以进行分派,并且在作业为 运行.

时无法反序列化

当您将 eloquent 模型(或模型集合)发送到队列作业时,Laravel 仅在调度作业时序列化模型的 ID。然后处理作业时,它会获取 ID 并从数据库中检索数据。

在这种情况下,您的 $subscribers 是 eloquent 个 ParticipantesEvento 个模型的集合。此外,由于您的查询,您的模型仅有的数据是用户的姓名和电子邮件。因此,当 Laravel 尝试序列化此集合的键时,它不会找到任何键。

即使您确实更新查询以在模型中包含 participantes_eventos.id 字段,当工作 运行 时,您的 subscribers 属性 将是一个新的没有您从原始查询中包含的用户数据的 ParticipantesEvento 模型集合。

您的代码表明您真正希望 $subscribers 成为与事件相关的用户。假设你已经建立了 eloquent 关系,你可以这样做:

$subscribers = $event->users;

如果您没有关系设置,请将其添加到您的 Evento 模型中。这通过 participantes_eventos table.

设置了从事件到用户的 many-to-many relationship
public function users()
{
    return $this->belongsToMany(User::class, 'participantes_eventos');
}

您也可以对证书执行相同的操作。将此方法添加到您的 Evento 模型以设置从事件到证书的 one-to-one relationship

public function certificate()
{
    return $this->hasOne(Certificado::class);
}

然后像这样使用它:

$certificate = $event->certificate;

嗯...似乎在执行作业时,SerializesModels 重复模型的查询,并且由于某种原因,它变坏了。我做了一个解决方法...... 在我分派作业的函数中,我没有将模型传递给作业,而是制作了结果数组。并将此数组传递给作业。这样job就不会重复查询了,只是读取接收到的静态数组:

$inscritos = ParticipantesEvento::join('users', 'participantes_eventos.user_id', '=', 'users.id')
    ->select('users.name', 'users.email')
    ->where('evento_id', '=', $evento->id)
    ->get();

$insc = array();
foreach ($inscritos as $inscrito) {
    $insc[] = $inscrito;
}

但是...

注意:

这在某些情况下可能会带来问题。如本文所述: https://gistlog.co/JacobBennett/e60d6a932db98985f160146b09455988 ,SerializesModel 重做查询的优点是从数据库中获取更新的数据。例如:如果用户在 his/her register after 中更改了您的电子邮件或姓名,我将静态数组发送到作业,当作业执行时,它将使用过时的用户信息。

但是,它现在起到了作用...虽然我认为这是解决此问题的更优雅的方法。感谢所有帮助!