Данные очереди Laravel не передаются из конструктора в обработчик - PullRequest
0 голосов
/ 09 апреля 2019

У меня проблема с работой в очереди 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 говорится, что переменные объявлены защищенными в работе, я уже пробовал использовать их как общедоступные. Та же проблема. У меня уже нет идей. Что я делаю не так ??

Ответы [ 2 ]

1 голос
/ 09 апреля 2019

Ваша коллекция красноречивых моделей структурирована неправильно.Из-за этого Laravel не может правильно сериализовать их для отправки и десериализации при запуске задания.

Когда вы отправляете красноречивую модель (или коллекцию моделей) в задание очереди, Laravel сериализует только идентификаторы моделейкогда работа отправляется.Когда задание затем обрабатывается, оно берет идентификаторы и получает данные из базы данных.

В этом случае ваш $subscribers является красноречивым набором ParticipantesEvento моделей.Кроме того, по вашему запросу единственными данными, которые имеют ваши модели, являются имя и адрес электронной почты пользователя.Поэтому, когда Laravel пытается сериализовать ключи этой коллекции, он не найдет никаких.

Даже если вы обновите свой запрос, включив в модель поле participantes_eventos.id, когда задание выполняется,Ваше свойство subscribers будет новой коллекцией моделей ParticipantesEvento без данных пользователя, которые вы указали в исходном запросе.

Ваш код показывает, что вы действительно хотите, чтобы ваш $subscribers был тем пользователем, который присоединен к событию.Предполагая, что у вас настроены красноречивые отношения, вы можете просто сделать это:

$subscribers = $event->users;

Если у вас нет настроек взаимоотношений, добавьте это в модель Evento.Это устанавливает отношение «многие ко многим» от событий к пользователям через таблицу participantes_eventos.

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

Вы можете сделать то же самое с сертификатом, тоже,Добавьте этот метод к вашей Evento модели, чтобы установить отношение один к одному от события к сертификату:

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

А затем использовать его следующим образом:

$certificate = $event->certificate;
0 голосов
/ 09 апреля 2019

Ну ... кажется, что когда задание выполняется, 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 в повторении запроса заключается в получении обновленных данных из базы данных. Например: если пользователь изменяет ваш адрес электронной почты или имя в своем реестре после , я отправляю статический массив в задание, когда задание выполняется, оно будет работать с устаревшей информацией пользователя.

Тем не менее, пока что все получилось ... хотя я думаю, что это более элегантное решение этой проблемы. Спасибо всем, кто помог!

...