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 中更改了您的电子邮件或姓名,我将静态数组发送到作业,当作业执行时,它将使用过时的用户信息。
但是,它现在起到了作用...虽然我认为这是解决此问题的更优雅的方法。感谢所有帮助!
我遇到了 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.
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 中更改了您的电子邮件或姓名,我将静态数组发送到作业,当作业执行时,它将使用过时的用户信息。
但是,它现在起到了作用...虽然我认为这是解决此问题的更优雅的方法。感谢所有帮助!