【问题标题】:Laravel queue data not being passed from constructor to handlerLaravel 队列数据未从构造函数传递到处理程序
【发布时间】:2019-04-08 21:42:45
【问题描述】:

我在使用 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。同样的问题。我已经没有想法了。我做错了什么??

【问题讨论】:

  • 你能不能试试把$this->subscribers = clone $s;,看看会发生什么?
  • @GTCrais 试过了。不工作... =/
  • 如果有帮助...这两个变量都是来自数据库的信息。有问题的变量和其他变量之间的唯一区别是它是一个集合,有很多订阅者。另外两个只有一个注册(一个事件和一个证书)。
  • 尝试$this->subscribers = "whatever"; 确认/消除$s 参数中的问题。
  • 我已经做过这个测试。在构造函数中为$this->subscribers 分配任何“任何”值,该值在处理程序中正常显示。

标签: php laravel queue laravel-queue


【解决方案1】:

您的雄辩模型集合结构不正确。因此,Laravel 无法在作业运行时正确序列化它们以进行调度和反序列化。

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

在这种情况下,您的$subscribersParticipantesEvento 模型的雄辩集合。此外,由于您的查询,您的模型拥有的唯一数据是用户的姓名和电子邮件。所以,当 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;

【讨论】:

  • 我没有这个结构。我有eventos 表,有'id'、'name'、'description' 等。我有users 表,有'id'、'name' 和'email'。我有一个participantes_evento 表,它“联合”了系统每个“evento”的订阅者,具有“id”、“evento_id”和“user_id”字段。使用$subscribers = $evento->users; 在这种结构中不起作用(是的,我知道它不是最正确的结构,但它是我必须处理的)。
  • 我刚刚为这个问题做了一个解决方法......但我会尝试这样做,如果可行,我会返回。
  • 宾果游戏!效果很好,伙计!非常感谢您的帮助!只需在certificate()函数中添加return,否则会抛出异常。我会把答案标记为正确的!再次感谢!
  • @AndréRaubach 呃,抱歉错字并感谢您的编辑。但是,是的,您所描述的是多对多关系,其中participantes_evento 表是将许多用户连接到许多事件的数据透视表,反之亦然。 belongsToMany 关系是您雄辩地建模的方式。很高兴你成功了!
【解决方案2】:

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

$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 重做查询的优点是从数据库中获取更新的数据。例如:如果用户在他/她的注册中更改了您的电子邮件或姓名我将静态数组发送到作业,当作业执行时它将使用过时的用户信息。

但是,它现在起到了作用……而我认为这是一个更优雅的解决方案。感谢所有帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-22
    • 2021-12-14
    • 1970-01-01
    • 2020-11-19
    • 2019-03-18
    • 1970-01-01
    • 2021-07-16
    • 1970-01-01
    相关资源
    最近更新 更多