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

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?

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 - how to pass variable from controller to job

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));
}
}

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;
}

How to call Facades method from boot method?

In laravel 6 app I created facade app/Facades/MyFuncsClass.php :
<?php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class MyFuncsClass extends Facade{
protected static function getFacadeAccessor() { return 'MyFuncsClass'; }
}
But I got error :
"message": "Non-static method App\\Helpers\\MyFuncsClass::debToFile() should not be called
statically",
calling it from boot method:
protected static function boot() {
parent::boot();
static::deleting(function($task) {
$hostel_image_image_path= Task::getTaskImagePath($task->id, $task->image);
MyFuncsClass::debToFile(print_r($hostel_image_image_path, true), '-9 $hostel_image_image_path::');
...
Is there is a way to escape this error and run MyFuncsClass::debToFile in boot method ?
MODIFIED :
Sure I registered my facade in config/app.php, 'providers' block :
...
App\Providers\MyFuncsClassProvider::class,
file app/Http/Helpers/MyFuncsClass.php has a lot of public methods, with heading:
<?php
namespace App\Helpers;
use Illuminate\Http\Request;
use Barryvdh\Debugbar\Facade as Debugbar;
use Carbon\Carbon;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
class MyFuncsClass {
public $concat_str_max_length = 50;
public $m_concat_str_add_chars = '...';
public function debToFile($contents, string $descr_text = '', bool $is_sql = false, string $file_name = '')
{
try {
...
and in app/Providers/MyFuncsClassProvider.php :
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\App;
class MyFuncsClassProvider extends ServiceProvider
{
/**
* Register services.
*
* #return void
*/
public function register()
{
App::bind('MyFuncsClass', function()
{
return new \App\Helpers\MyFuncsClass;
});
}
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
//
}
}
Actually I can call \MyFuncsClass::debToFile( ok from not static methods, like control actions, but I have the error
calling from static boot method...
MODIFIED # 2 :
With real time facades https://laravel.com/docs/5.7/facades#real-time-facades defintions
I tried
<?php
namespace App;
use DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use App\Facades\MyFuncsClass;
use App\Http\Helpers\MyFuncsClassContainer; // Alias for my helper class
use Illuminate\Database\Eloquent\Model;
use Barryvdh\Debugbar\Facade as Debugbar;
class Task extends Model
{
use Sluggable;
protected $table = 'tasks';
protected $primaryKey = 'id';
}
protected static function boot() {
parent::boot();
static::deleting(function($task) {
$hostel_image_image_path= Task::getTaskImagePath($task->id, $task->image);
\Log::info( '-9 $hostel_image_image_path::' );
\Log::info( print_r($hostel_image_image_path, true) );
$myFuncsClassCore = factory(MyFuncsClassContainer::class)->create();
$myFuncsClassCore->debToFile(' debToFile string REDSA');
Bur anywat I got error :
Cannot declare class App\Helpers\MyFuncsClassContainer, because the name is already in use {"userId":1,"exception":"[object] (Symfony\\Component\\Debug\\Exception\\FatalErrorException
I tried a way to rename my helper class to “MyFuncsClassContainer”, supposing
having the same name for helper and facade could raise error, but failed
If there is a way to fix this error ?
Thanks!

Laravels 'Should Queue" resets mail text to default

i have a problem woth combining notifications and queue in laravel...
if i dont use queue and write notification like this
namespace App\Notifications;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\MailMessage;
class InterestingOfferPosted extends Notification
{
public $offer;
public function __construct($offer)
{
$this->offer = $offer;
}
public function via($notifiable)
{
return ['mail'];
}
public function toMail($notifiable)
{
return (new MailMessage)
->subject('New Offer')
->line("You have new offer: ".$this->offer->name }
}
this works fine, i get correct text at the end, however if i get this class to implement "Illuminate\Contracts\Queue\ShouldQueue" class and use "Illuminate\Bus\Queueable" trait users are receiving default laravels "The introduction to the notification." mail.
queues are working nice in any other cases, so i think i got that right, but in this particular case it alters final result.
Any ideas?
I think you are not implementing queue interface here
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\MailMessage;
class InterestingOfferPosted extends Notification implements ShouldQueue{
use Queueable;

Resources