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

Php Laravel队列数据未从构造函数传递到处理程序,php,laravel,queue,laravel-queue,Php,Laravel,Queue,Laravel Queue,我对Laravel 5.6排队作业有问题。我将3个参数传递给构造函数。此时,我检查了所有参数,所有参数都有数据。但是当我运行作业时,其中一个在处理程序中是空的 这是分派作业的功能: public function send() { $event = Evento::find($id); $subscribers = ParticipantesEvento::join('users', 'participantes_eventos.user_id', '=', 'users.id'

我对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
    }
}
这就是工作:

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的文档中说要将变量声明为作业中受保护的变量,但我已经尝试将它们作为公共变量。同样的问题。我已经没有主意了。我做错了什么???

你收集的有说服力的模型结构不正确。因此,Laravel无法在作业运行时正确序列化它们以进行分派和取消序列化

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

在本例中,您的
$subscribers
participatesevento
模型的有力集合。此外,由于您的查询,您的模型仅有的数据是用户的姓名和电子邮件。因此,当Laravel尝试序列化此集合的键时,它将找不到任何键

即使您确实更新了查询以在模型上包含
participantes\u eventos.id
字段,当作业运行时,
subscribers
属性将是ParticipantesEvento模型的新集合,而不包含从原始查询中包含的用户数据

您的代码显示您真正想要的
$subscribers
是附加到事件的用户。假设你建立了雄辩的人际关系,你可以这样做:

$subscribers = $event->users;
如果未设置关系,请将其添加到
Evento
模型中。这将通过
participantes\u eventos
表设置从事件到用户的权限

public function users()
{
    return $this->belongsToMany(User::class, 'participantes_eventos');
}

您也可以对证书执行同样的操作。将此方法添加到
Evento
模型中,以设置从事件到证书的:

public function certificate()
{
    return $this->hasOne(Certificado::class);
}
然后像这样使用它:

$certificate = $event->certificate;

嗯……似乎在执行作业时,序列化模型会重复模型的查询,并且由于某种原因,它会出错。我做了一个变通办法。。。 在分派作业的函数中,我没有将模型传递给作业,而是使用结果创建和数组。并将此数组传递给作业。这样,作业将不会重复查询,而只是读取接收到的静态数组:

$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;
}
但是

注意:

在某些情况下,这可能会带来问题。如本文所述,SerializesModel重做查询的优点是从数据库获取更新的数据。例如:如果用户在我将静态数组发送到作业后更改了他/她的注册表中的电子邮件或姓名,则作业执行时将使用过时的用户信息


然而,现在它成功了……而我认为这是一个更优雅的解决方案。感谢所有的帮助

你能试着把订阅者=克隆$s,只是想看看会发生什么?@GTCrais尝试过。不工作=/如果有帮助的话……这两个变量都是来自数据库的信息。问题变量与其他变量之间的唯一区别在于它是一个集合,有许多订阅者。另外两个只有一个寄存器(一个事件和一个证书)以确认/消除
$s
参数中存在的问题。我已经做了此测试。将任何“whatever”值赋给构造函数中的
$this->subscribers
,该值在处理程序中正常显示。我没有此结构。我有
eventos
表,其中包含“id”、“name”、“description”等。我有
users
表,其中包含“id”、“name”和“email”。我有一个
participantes\u evento
表,该表“联合”了系统中每个“evento”的订阅者,其中包含“id”、“evento\u id”和“user\u id”字段。使用
$subscribers=$evento->users
在此结构中不起作用(是的,我知道这不是最正确的结构,但这是我必须处理的)。我刚刚为这个问题制定了一个解决方案……但我会尝试这样做,如果可行的话返回。宾果!那很好用,伙计!非常感谢你的帮助!只需在
certificate()
函数中添加
return
,否则会引发异常。我将把答案标为正确!再次感谢@安德烈·劳巴赫,对不起,我打错了,谢谢你的编辑。但是,是的,您描述的是一种多对多关系,
participantes\u evento
表是一个数据透视表,它将许多用户连接到许多事件,反之亦然。
belongtomany
关系就是你如何用雄辩的方式来建模的。很高兴你成功了!