Laravel - how to pass variable from controller to job - laravel

Sorry if this is a noob question.
I used to send emails directly through the controller, like so:
Mail::to($user)->send(new RegisterConfirmation($user));
As you can see I also pass the $user into the email where I can use that user's information, like "Hello {{$user->username}}!"
But now instead I want to queue emails, so in my controller I now have this:
RegisterConfirmationJob::dispatch($user);
In my job, I have the following:
public function __construct(User $user)
{
$this->user = $user;
}
public function handle()
{
$user = $this->user;
Mail::to($user)->send(new RegisterConfirmation($user));
}
When I run this, it returns the following error:
[2021-07-09 20:33:57] local.ERROR: Undefined property:
App\Jobs\RegisterConfirmationJob::$user {"exception":"[object]
(ErrorException(code: 0): Undefined property:
App\Jobs\RegisterConfirmationJob::$user at
/home/vagrant/projects/app/Jobs/RegisterConfirmationJob.php:37)
[stacktrace]
Why is this happening?
EDIT:
As requested, here is my entire RegisterConfirmationJob class:
<?php
namespace App\Jobs;
use App\Mail\RegisterConfirmation;
use App\User;
use Illuminate\Support\Facades\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class RegisterConfirmationJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct(User $user)
{
$this->user = $user;
}
public function handle()
{
$user = $this->user;
Mail::to($user)->send(new RegisterConfirmation($user));
}
}

It's simple, you hadn't declared $user as a class property, that is the error meaning.
I recommend you declare it as public property to use it at blade template

Yeah bro, it's not a Laravel problem, it's a PHP class definition problem, you can solve this by declaring the $user property, like that:
<?php
namespace App\Jobs;
use App\Mail\RegisterConfirmation;
use App\User;
use Illuminate\Support\Facades\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class RegisterConfirmationJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $user; // you forgot of put this line
public function __construct(User $user)
{
$this->user = $user;
}
public function handle()
{
$user = $this->user;
Mail::to($user)->send(new RegisterConfirmation($user));
}
}

Related

Laravel 8 jobs not dispatching

I have this Job
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Http\Traits\CreateTrait;
class CreateJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, CreateTrait;
protected $contactForm;
public function __construct($contactForm)
{
$this->contactForm = $contactForm;
}
public function handle()
{
//This connects to SSH and takes 5-10s
$this->CreateOnetime($this->contactForm->room_id, $this->contactForm->company_id, $this->contactForm->id);
}
}
Then I try in controller
use App\Jobs\CreateJob;
class ContactFormController extends Controller
{
public function save(StoreContactFormRequest $request, $cid, $rid){
$validated = $request->validated();
$validated['room_id'] = $rid;
$validated['company_id'] = $cid;
$contactForm = ContactForm::create($validated);
CreateJob::dispatch($contactForm);
return back();
}
}
Nothing written in the DB, though I have QUEUE_DRIVER=database in the .env file.
The function runs synchronously, so it does not create the Job somehow, just runs it.
Problem was I had QUEUE_CONNECTION=sync somewhere after QUEUE_DRIVER=database

Laravel: Passing a class name from a Controller to a Job

I'm trying to pass a certain class name from the controller to a job file through
Job::dispatch($className);
I've tried passing it as a string and passing it as a ClassName::class but none of these methods work
The code in the Job file looks something along the lines of this:
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class BreakUpArraysJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $products;
protected $jobName;
public function __construct($products, $jobName)
{
$this->products = $products;
$this->jobName = $jobName;
}
/**
* Execute the jobName.
*
* #return void
*/
public function handle()
{
$productArrays = array_chunk($this->products, 5000);
foreach($productArrays as $productArray){
$this->jobName::dispatch($productArray);
}
}
}
the $jobname variable is the className I'm trying to pass.
I also need to note that I'm passing the classname of a different Job from the Controller, by which I mean the job handler is supposed to call another Job through the variable.
I do not think your syntax is working, an alternative approach would be to do it like this.
dispatch(new $this->jobName($productArray));
in your job construct add class Name that your var is instance of before $product like this:
public function __construct(Product $products, $jobName)
{
$this->products = $products;
$this->jobName = $jobName;
}

Pusher notifications not triggering in laravel

I created a new event, and signed up at pusher in order to test my notifications.
This is how my controller looks like:
public function view_posts(){
$user = User::find(6999);
event(new TestNotification($user));
return $user;
}
And inside the TestNotification I initialized my constructor:
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class TestNotification implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user;
public function __construct($user)
{
//
$this->user = $user;
}
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
I have my .env setup. ( All the details are fake )
BROADCAST_DRIVER=pusher
CACHE_DRIVER=file
SESSION_DRIVER=file
SESSION_LIFETIME=120
QUEUE_DRIVER=database
PUSHER_APP_NAME=testapp
PUSHER_APP_ID=2655265
PUSHER_APP_KEY=ffgf5ghfgh1g5
PUSHER_APP_SECRET=6rergf4erg4er
PUSHER_APP_CLUSTER=us2
When I visit my url, the user gets returned, fine, but when I go to pusher console, I don't see the user array or anything related to the notification.
Note: If I change my broadcast_driver to log, it doesn't work either
Is there anything that I am possibly missing?

Laravel custom event not being triggered by eloquent event when model update run as scheduled task

I have a custom event being triggerred by the updated Eloquent model event. This custom event is working when an update is done manually, (ie outside a Scheduled Task) but not when the update is done via a Scheduled Task
Model code
<?php namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Location extends Model {
self::updated(function ($location) {
event(new LocationRefresh($location));
});
}
Here's the event listener:
<?php namespace App\Events;
use App\Events\Event;
use App\Models\Location;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class LocationRefresh extends Event implements ShouldBroadcast
{
use SerializesModels;
public $id;
public $closed;
public $closed_until;
public function __construct(Location $location)
{
$this->id = $location->id;
$this->closed = $location->closed;
$this->closed_until = $location->closed_until;
}
public function broadcastOn()
{
return [
'private-location-'.$this->id
];
}
}
Any ideas?

Request class injection in repository class

I have following repository class
<?php
namespace App\Repositories;
use App\Customer;
use App\Comment;
use App\CustomerCode;
use Illuminate\Support\Facades\Request;
class CustomerRepository {
use ValidatesRequests;
public function getAll($search=null,Request $request)
{
if($search){
return Customer::where('name','like',"%$search%")->paginate(5);
}
return Customer::paginate(5);
}
}?>
and controller class
<?php
namespace App\Http\Controllers;
use App\Repositories\CustomerRepository;
use Illuminate\Http\Request;
class CustomerController extends Controller{
private $customerRepo;
function __construct(CustomerRepository $customerRepo){
$this->customerRepo = $customerRepo;
}
function index(Request $request){
return $this->customerRepo->getAll($request->input('search',null));
}
}
this gives me error
Type error: Argument 2 passed to
App\Repositories\CustomerRepository::getAll() must be an instance of
Illuminate\Support\Facades\Request, none given, called in
C:\xampp\htdocs\avmaxapi\app\Http\Controllers\CustomerController.php
on line 21
i know i havenot passed 2nd argument but should not it inject automatically
and i donot want to pass request object everytime from controller;
use use Illuminate\Http\Request;
and not: use Illuminate\Support\Facades\Request;
at the following:
<?php
namespace App\Repositories;
use App\Customer;
use App\Comment;
use App\CustomerCode;
use Illuminate\Http\Request;
class CustomerRepository {
use ValidatesRequests;
public function getAll($search=null,Request $request)
{
if($search){
return Customer::where('name','like',"%$search%")->paginate(5);
}
return Customer::paginate(5);
}
}?>

Resources