RelationNotFoundException error only in laravel dispatched jobs - laravel

I have a very strange error in laravel 7 where I have defined a hasOne relationship in the User Model called user_badge
public function userBadge()
{
return $this->hasOne(UserBadge::class, 'id', 'user_badge_id');
}
I have added user_badge_id to the users table and I have also made the user_badges table which holds the badge information. When a job runs in the background, I get the following error
Illuminate\Database\Eloquent\RelationNotFoundException: Call to undefined relationship [userBadge] on model [App\User]. in /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/RelationNotFoundException.php:34
Navigating throughout the site I get no issue at all.
This issue occurs when sending an email to the job queue. It happens to all notifications that is sent. Further to this, sometimes the email does get sent but most of the time it doesn't. The code is below for one of the notification
class NewFollowUserNotification extends Notification implements ShouldQueue
{
use Queueable;
public $sender;
public $receiver;
/**
* Create a new notification instance.
*
* #param User $sender
* #param User $receiver
*/
public function __construct(User $sender, User $receiver)
{
$this->sender = $sender;
$this->receiver = $receiver;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
if (Profile::sendEmailNotification('NewFollowUserNotification', $this->receiver)) {
return ['database', 'mail', 'broadcast'];
} else {
return ['database', 'broadcast'];
}
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
$user_notifications = UserNotifications::create('NewFollowUserNotification');
$user_notifications->setUsername($this->receiver->username);
$user_notifications->setEmailTemplate(EmailTemplate::getDefaultEmail());
$user_notifications->setButtonUrl(config('app.url').'/member/profiles/'.$this->sender->username);
$notification = $user_notifications->getEmailNotification();
$user_notifications->setTags('{receiver_first_name}', $this->receiver->first_name);
$user_notifications->setTags('{receiver_last_name}', $this->receiver->last_name);
$user_notifications->setTags('{receiver_full_name}', $this->receiver->first_name . ' ' . $this->receiver->last_name);
$user_notifications->setTags('{sender_first_name}', $this->sender->first_name);
$user_notifications->setTags('{sender_last_name}', $this->sender->last_name);
$user_notifications->setTags('{sender_full_name}', $this->sender->first_name . ' ' . $this->sender->last_name);
return $user_notifications->sendUserNotification($notification);
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toArray($notifiable)
{
return [
'heading' => 'New contact request',
'message' => $this->sender->first_name.' '.$this->sender->last_name.
' sent you a contact request',
'link' => '/member/profiles/'.$this->sender->username,
'username' => $this->sender->username,
'module' => 'user',
];
}
Locally on my own development machine everything works fine.

The issue here was the serialization of models within a job. There are limitations as to how much data jobs can serialize so I ended up passing the id of the model to the job and accessing the necessary information from there.

Related

Why is the data column empty? Laravel Notifications

I am trying to set up database notification, but the data I am sending for the 'data' column isn't showing up...
My notification class:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use App\User;
use App\Admin;
class UserAddedToStudio extends Notification implements ShouldQueue
{
use Queueable;
public $user;
public $admin;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct(User $user, Admin $admin)
{
$this->user = $user;
$this->admin = $admin;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['mail', 'database'];
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->subject('Welcome to '.$this->admin->name.'\'s studio')
->line('Hi '.$this->user->name.'. Your request to join '.$this->admin->name.'\'s studio has been accepted! Now you can start registering for lessons.')
// ->action('Notification Action', url('/'))
->line('Thank you for using our application!');
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toDatabase($notifiable)
{
return [
'message' => 'You have been added to the studio'
];
}
}
In my notifications table on MySQL all the columns are filled except for the data column. There I only get an empty array []. but why?? so frustrating.... :(
Here is the screenshot from my phpmyadmin.
Try to use toArray() instead of toDatabase()
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toArray($notifiable)
{
return [
'message' => 'You have been added to the studio'
];
}
as you use Queue you should restart the queue worker.
php artisan queue: work
Remember, queue workers, are long-lived processes and store the booted application state in memory. As a result, they will not notice changes in your code base after they have been started. So, during your deployment process, be sure to restart your queue workers. In addition, remember that any static state created or modified by your application will not be automatically reset between jobs.

Passing data to notification in laravel

Been stumped for awhile on how to pass two variables into a notification and have that notification include an action that contains a route with a token. The use case is that my application allows users (called advisors here) to give access to other users. If the added users are not already registered, their accounts will be created and they will receive an email with a token to complete their registration.
I have the following in my AddAdvisorsController:
else {
$newadvisor = Advisor::create($data);
$newadvisor->save();
$newadvisorID = $newadvisor->id;
$newAdvisorEmail = $newadvisor->email;
//create a token
$token = Str::random(60);
//email advisor and pass $token variable to notification
$newadvisor->notify(new NewAdvisorNotification($token, $newAdvisorEmail));
I have the following in my NewAdvisorNotification:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class NewAdvisorNotification extends Notification
{
use Queueable;
public $token;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct($token, $newAdvisorEmail)
{
//
$this->token = $token;
$this->newAdvisorEmail = $newAdvisorEmail;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->line('You are receiving this email because we received a new account request for your email.')
->action('Notification Action', route('new.advisor', [$this->token, $this->newAdvisorEmail]))
// ->action('Notification Action', route('advisor/new-account/{{ $token }}/{newAdvisorEmail}'))
->line('If you did not request a password reset, no further action is required.');
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}
The new user is getting created properly in the database, but I get an error saying:
Missing required parameters for [Route: update.advisor] [URI: advisor/new-account/{token}/{newAdvisorEmail}]. (View: C:\xampp\htdocs\HealthHub\resources\views\auth\new-accounts\advisor-new-account.blade.php)
I have the following routes:
Route::get('/advisor/new-account/{token}/{newAdvisorEmail}', 'NewAdvisorController#showNewAccountForm')->name('new.advisor');
Route::post('/advisor/new-account/{token}/{newAdvisorEmail}', 'NewAdvisorController#updateNewAccount')->name('update.advisor');
});
I think my code is having errors with this line:
->action('Notification Action', route('new.advisor', [$this->token, $this->newAdvisorEmail]))
However, I am not sure how to fix it
You error clearly states you are missing parameters for your route. The way to specify route parameters is by name, so declare an associate array with the route parameter name as the key.
->action('Notification Action', route('new.advisor', ['token' => $this->token, 'newAdvisorEmail' => $this->newAdvisorEmail,]))

Laravel 5.8 on demand notification error Call to a member function create() on null

When I do this, the user receives email without error:
Notification::send($user, new TicketNotification($details));
But, when I do this, the user also receives an email, but with an error in the screenshot below
Notification::route('mail', 'email_of_non-db_user')->notify(new TicketNotification($details));
Error: Call to a member function create() on null
Do have any idea why? How can I avoid this error?
I have to use On Demand Notification because I need to send a notification to someone who is not stored as a "user".
i think try this one
in TicketNotification update via method with this for only send to mail.
But u r also saved notification into database..
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['mail'];
}
Thanks Jignesh, your answer works.
Sorry Thamer, I should have posted the whole code from the beginning.
Before, it was :
return ['mail','database'];
Now only :
return ['mail'];
Then, there is no error anymore.
Here my TicketNotification that made the error:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
class TicketNotification extends Notification
{
use Queueable;
private $details;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct($details)
{
$this->details = $details;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['mail','database'];
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->subject($this->details['subject'])
->greeting($this->details['title'])
->line($this->details['body'])
->line($this->details['links'])
;
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toDatabase($notifiable)
{
return [
'order_id' => $this->details['order_id']
];
}
}
Add this to your via method to use the same Notification for all your issues:
public function via($notifiable)
{
$availableChannels = [
'mail' => 'mail',
'database' => 'database',
'slack' => 'slack',
'telegram' => TelegramChannel::class
];
$channels = [];
foreach ($availableChannels AS $channel => $driver) {
if ($notifiable->routeNotificationFor($channel)) {
$channels[] = $driver;
}
}
return $channels;
}
You can now use On-Demand Notifications or fire the notificaton on users, without having to make multiple Notifications for each Channel or ON-DEMANDS etc...

Notify Slack send Array

im trying to send some values from a DB with Notify to Slack. Somehow every time I load my Website the only message I get is "Array" and not the data from the DB.
This is my Notifications .php
class InventoryReStock extends Notification
{
use Queueable;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct($reorder)
{
$this->reorder = $reorder;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['slack'];
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toSlack($notifiable)
{
return (new SlackMessage)
->content([$this->reorder]);
}
This is the function that Im using on my controller to get the data form the Db
public function index()
{
//shows all the products in the database in an overview
$products = Product::all()->toArray();
$reord = Product::select('Product_Name')->where('Number_Runs', '<=', '5')->get();
$reorder = json_decode(json_encode($reord), true);
Notification::route('slack', 'https://hooks.slack.com/services/..../...../......')->notify(new InventoryReStock($reorder));
return view('products.lab_inventory_overview', compact('products', 'reorder'));
}
and this is my User.php
public function routeNotificationForSlack($notification)
{
Return 'https://hooks.slack.com/services/..../...../......';
}
Never mind, I found a solution . Just converting the array to string makes it work.
$reorder = implode(', ', array_flatten($reorde));

Laravel Notification with ShouldQueue: toDatabase store different [data]

I have ServiceOrderCreated.php notification and want to use ShouldQueue, but it stores notification other than when I don't use ShouldQueue.
These are data sent to ServiceOrderCreated Class:
//notification
class ServiceOrderCreated extends Notification implements ShouldQueue
{
use Queueable;
protected $serviceOrder;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct(ServiceOrder $serviceOrder)
{
$this->serviceOrder = $serviceOrder;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['mail', 'database'];
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return json
*/
public function toDatabase($notifiable)
{
//dd($this->serviceOrder);
return [
$this->serviceOrder
];
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
$message = new MailMessage;
$message->subject('Sportservis-Hostivice: Nová zákazka č. '.$this->serviceOrder->id);
foreach ($this->serviceOrder->serviceOrderItem as $item) {
$message->line('<li>'.$item->customerOrderAsset->name.' - '.$item->serviceType->name.' - '.$item->price.'</li>');
}
return $message;
}
Problem is, that when I remove "implements ShouldQueue", it stores whole collection ($newServiceOrder) to Notifications table ([data] column). When "implements ShouldQueue" is in place, only bare model without relations is stored to Notifications table.
Any idea? Did I miss Something?
UPDATE
This is the collection which is passed from ServiceOrderController.php to notification.
$newServiceOrder = ServiceOrder::with(['serviceOrderItem', 'serviceOrderItem.serviceType', 'serviceOrderItem.customerOrderAsset', 'customer'])->find($serviceOrder->id)
$newServiceOrder->customer->notify(new ServiceOrderCreated($newServiceOrder));
UPDATE 2:
This is what is store in notifications table when I don't use ShouldQueue:
https://pastebin.com/hXF03tEa
And this is what is stored when I use ShouldQueue:
https://pastebin.com/Vb6hFZkH

Resources