我在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的文档说要在工作中将变量声明为受保护的变量,但我也已经尝试将它们作为公共变量使用。同样的问题。我已经没有主意了。我做错了什么?
答案 0 :(得分:2)
您的口才模型集合结构不正确。因此,Laravel无法在作业运行时正确地对其进行序列化以进行分发和反序列化。
当您将雄辩的模型(或模型集合)发送到队列作业时,Laravel仅在调度作业时序列化模型的ID。处理完作业后,它将获取ID并从数据库中检索数据。
在这种情况下,您的$subscribers
是ParticipantesEvento
模型的雄辩的集合。同样,由于您的查询,模型拥有的唯一数据是用户的姓名和电子邮件。因此,当Laravel尝试序列化此集合的键时,将找不到任何键。
即使您确实更新了查询以在模型上包含participantes_eventos.id
字段,运行作业时,您的subscribers
属性也将是ParticipantesEvento模型的新集合,而无需包含用户数据从您的原始查询。
您的代码显示,您真正希望$subscribers
成为事件附属的用户。假设您已建立了雄辩的关系,则只需执行以下操作即可:
$subscribers = $event->users;
如果没有设置人际关系,请将其添加到您的Evento
模型中。这样会通过participantes_eventos
表将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;
答案 1 :(得分:1)
好吧...似乎在执行作业时,SerializesModels重复对Model的查询,由于某种原因,它变得很糟糕。我做了一个解决方法... 在我分派工作的函数中,我没有将模型传递给工作,而是对结果进行了排列。并将此数组传递给作业。这样,作业将不会重复查询,而只是读取收到的静态数组:
$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重做查询的优点是从数据库中获取更新的数据。例如:如果用户在之后之后在其寄存器中更改了您的电子邮件或姓名,我会将静态数组发送给该作业,则在该作业执行时,它将使用过时的用户信息。
但是,它暂时起到了作用……而我认为这是一个更优雅的解决方案。感谢所有的帮助!