Sachin Kumar
Sachin Kumar

Reputation: 3240

Put function in Queue but not loaded relation data | Laravel Queue

I need to generate a pdf of user with their related data. I have created a function in controller to generate pdf(using snappy-pdf package). Data is loaded properly, pdf generated and uploaded on S3 successfully. Now I am trying to put that function in queue with user data. But data is not loaded for generation pdf. Instead it only laod the user model data but not the related data (like property and contact).

$user = User::where("id", 83)->with(['property', 'contacts'])->first();
$contact_list = [];
if(count($user->contacts)){
    foreach ($user->contacts as $contact) {
        array_push($contact_list, $contact->contactDetails->name);
    }
} 
$user->contact_list = $contact_list;
return view('pdf_view', ["user" => $user]);
if($request->has('download')) {

    // dispatch the event
    /*$pdf = PDF::loadView('pdf_view', ["user" => $user]);
            // upload pdf
        Storage::disk('s3')->put("user-invoice/user.pdf", $pdf->output(), 'public');*/
    dispatch(new GenerateSignedDocument($user));
    return "done";         
}

And here is my job file.

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Log;
use PDF;
use Storage;

class GenerateSignedDocument implements ShouldQueue
{
    use InteractsWithQueue, Queueable, SerializesModels;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    private $user;
    public function __construct($user)
    {
        $this->user = $user;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
         // Log::info('Showing user: '.$this->user);
        $pdf = PDF::loadView('pdf_view', ["user" => $this->user]);
            // upload pdf
        Storage::disk('s3')->put("user-invoice/user.pdf", $pdf->output(), 'public');
    }
}

Upvotes: -1

Views: 1067

Answers (2)

Sachin Kumar
Sachin Kumar

Reputation: 3240

I don't know this is the perfect solution or not but I do this and work fine. I called the required function(uploadUserDocument) for performing pdf generation in the handler function.

/**
 * Execute the job.
 *
 * @return void
 */
public function handle()
{
    app('App\Http\Controllers\UserController')->uploadUserDocument($this->user_id);
}

and dispatch the event as it is in the controller

dispatch(new GenerateSignedDocument(83));

and put the required code for generating pdf in the uploadUserDocument function like this.

/**
     * Function is used to Save document to s3 cloud
     * @param $user_id
     * @return Response
     */
    public function uploadUserDocument($user_id){
        $pdf = PDF::loadView('pdf_view', ["user" => $user]);
            // upload pdf
        Storage::disk('s3')->put("user-invoice/user.pdf", $pdf->output(), 'public');
    }

Upvotes: 1

Devon Bessemer
Devon Bessemer

Reputation: 35357

The SerializesModels trait only stores the model's key and reloads the model from the database when it is unserialized, so this is likely not going to load your relationships.

This is usually a big benefit as you'll receive fresh data when your queued job actually runs, not the data from when the job was scheduled.

In any case, it's probably best to either:

  1. Load the relationships the job requires in the job itself and not rely on them being preloaded.

or

  1. Pass the property and contacts as separate dependencies to your job class.

Upvotes: 2

Related Questions