Laravel - Notification Mail ShouldQueue does't work - php

I would like to send email notifications using the queue.
I have created the queue table and tracked all the documentation related to this topic but the notifications are sent without going through the queue.
In my controller :
Notification::send(User::role('team')->get(), new NewExchangeToCollaboratorNotification($user, $exchange, $firstMessage));
And my notification code is :
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Setting;
class NewExchangeToCollaboratorNotification extends Notification implements ShouldQueue
{
use Queueable;
protected $user; protected $exchange; protected $exchangeMessage; protected $replyToAddress;
public function __construct($user, $exchange, $exchangeMessage)
{
$this->user = $user;
$this->exchange = $exchange;
$this->exchangeMessage = $exchangeMessage;
$this->replyToAddress = Setting::get('MAIL_REPLY_TO_ADDRESS', env('MAIL_FROM_ADDRESS'));
}
public function via($notifiable)
{
return ['mail'];
}
public function toMail($notifiable)
{
return (new MailMessage)->view(
'emails.exchanges.new',
[
'user' => $this->user,
'exchangeMessage' => $this->exchangeMessage,
'exchange' => $this->exchange
]
) ->subject('New exchange: ' . $this->exchange->title)
->from(env('MAIL_FROM_ADDRESS'))
->replyTo($this->replyToAddress);
}
}
Are the notifications queueable ? Is there something I'm doing wrong ?
Thank you for your answers :)
EDIT :
Add delay does not work too.
$when = now()->addMinutes(10);
Notification::send(User::role('team')->get(), (new NewExchangeToCollaboratorNotification($user, $exchange, $firstMessage))->delay($when));
EDIT 2 :
No failed job

Make sure your .env is:
QUEUE_CONNECTION=database

Related

Getting error "Argument 1 passed to Modules\\Admin\\Events\\"

I am new in laravel. I am creating mailer in laravel in which i created event for it. But from postman when i am hitting the api, i am getting error:
Argument 1 passed to Modules\\Admin\\Events\\NewsLetterSubscribeEvent::__construct() must be an instance of App\\Models\\NewsletterSubscription, array given, called in /home/ashish/projects/backend/laravel-backend/app/Repositories/NewsletterSubscriptionRepository.php on line 25",
What can be issue, i imported all classes, but still getting the error.
this is my code
repository
class NewsletterSubscriptionRepository extends EloquentBaseRepository
{
public $model = NewsletterSubscription::class;
public function create($data)
{
try{
DB::beginTransaction();
event(new NewsLetterSubscribeEvent($data));
DB::commit();
} catch(Exception $exception){
DB::rollBack();
throw $exception;
}
return parent::create($data); // TODO: Change the autogenerated stub
}
}
event file
<?php
namespace Modules\Admin\Events;
use App\Models\NewsletterSubscription;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
use Modules\Admin\Mail\NewsLetterSubscribeMail;
class NewsLetterSubscribeEvent
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* SendMailToAgentEvent constructor.
* #param User $user
*/
public function __construct(NewsletterSubscription $user)
{
dd($user);
Mail::to($user->email)->send(new NewsLetterSubscribeMail($user));
}
}
model
<?php
namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
class NewsletterSubscription extends Model
{
const ACTIVE = 1;
const INACTIVE = 0;
protected $table = 'newsletter_subscription';
protected $casts = [
'is_active' => 'int'
];
protected $fillable = [
'email',
'is_active'
];
}
Am i forgetting any namespace, or i am doing something wrong? Thanks in advance.
Error is saying must be an instance of NewsletterSubscription but you are passing array to fix this
public function __construct($user) // remove NewsletterSubscription from here
{
dd($user);
Mail::to($user->email)->send(new NewsLetterSubscribeMail($user));
}
or
class NewsletterSubscriptionRepository extends EloquentBaseRepository
{
public $model = NewsletterSubscription::class;
public function create($data)
{
$newsLetterSubscribeEvent = null;
try{
DB::beginTransaction();
$newsLetterSubscribeEvent = NewsletterSubscription::create($data); // TODO: Change the autogenerated stub
event(new NewsLetterSubscribeEvent($newsLetterSubscribeEvent)); // passing model instace
DB::commit();
} catch(Exception $exception){
DB::rollBack();
throw $exception;
}
return $newsLetterSubscribeEvent;
}
}

laravel mail how to properly implement into the system

So I am trying to implement a command that notifies all users that are subscribes to an event with command that does an check every day. I was reading Laravel mail docs 7.x so there example is about order system where they send the mail with this peace of code
foreach (['taylor#example.com', 'dries#example.com'] as $recipient) {
Mail::to($recipient)->send(new OrderShipped($order));
}
what as it looks takes the email of of the loop and then send an email toward that adress.
So I made a mail class php artisan make:mail NotifyUserOfEvents
and where I made this code
<?php
namespace App\Mail;
use App\Event;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class NotifyUserOfEvents extends Mailable
{
use Queueable, SerializesModels;
protected $event;
public function __construct(Event $event)
{
$this->event = $event;
}
public function build()
{
return $this->view('mails.NotifyUserOfEvents')
->with([
'name' => $this->event->name,
'date' => $this->event->settings->start_date,
]);
}
}
but when I try to call this class with this function
<?php
namespace App\Console\Commands;
use App\Event;
use App\RegistrationEvents;
use App\User;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
class NotifyUsersForEvents extends Command
{
protected $signature = 'NotifyUsersForEvents';
protected $description = 'Notify the user for the event. test run with -> php artisan schedule:run';
public function __construct()
{
parent::__construct();
}
public function handle()
{
Log::debug('this works every minute');
$events = Event::query()
->with('settings')
->has('settings')
->get();
foreach ($events as $event) {
$week = Carbon::now()->addWeek();
$sixDays = $week->copy()->subDay();
if (Carbon::create($event->settings->date_start)->between($week, $sixDays)) {
$subscriptions = RegistrationEvents::query()
->where('event_id', $event->id)
->get();
foreach ($subscriptions as $subscription) {
var_dump($subscription->user_id);
$user = User::findOrFail($subscription->user_id);
Mail::to($user->email)->send($event);
var_dump($user->email);
}
}
}
}
}
it returns this error: Argument 1 passed to Illuminate\Database\Eloquent\Model::__construct() must be of the type array, object given, called in so do I need to change the way I call the mail class or do I need to add something to the Event Model?
also the event.php
use Illuminate\Contracts\Mail\Mailable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Event extends Model implements Mailable
{
use SoftDeletes;
public function settings(){
return $this->hasOne('App\EventSettings', 'event_id');
}
}
You must pass to send function an object of your NotifyUserOfEvents, not an Event object.
Try this:
Mail::to($user->email)->send(new NotifyUserOfEvents($event));
Referring to this line:
Mail::to($user->email)->send(new Event($event));
you are creating a new Event passing to the constructor another Event... you probably never define a constructor that accept as first parameter an Event...
But despite that, what's the sense of doing this? To Mail::send you have to pass a Mailable, not an event, and i'm pretty sure you don't need a new event, so i believe you would want to do something like this:
use App\Mail\NotifyUserOfEvents; // or whatever namespace you have to the mail
Mail::to($user->email)->send(new NotifyUserOfEvents($event));
$user = User::find($id);
$email = $user->email;
if(Helper::isValidEmail($email))
{
Mail::send('emails.applicant_reference',
$emailParameters, function($message) use ($email, $name, $subject){
$message->to($email, $name)
->subject($subject);
});
$applicantName = null;
$subject = " Application received for ".$applicantName;
$emailParameters = ["applicantName" => $applicantName, "proposerName" => $proposerName, "seconderName" => $seconderName];
try
{
Mail::send('emails.application', $emailParameters, function($message) use ($applicantName, $subject){
$message->to(['test#gmail.com','test#gamil.com'], " Test Email Function ")
->subject($subject);
});
} catch (Exception $ex){ Log::error("UserController".$ex->getMessage());
}

How to Control Events from firing in Laravel

I have an Event that fires off a Welcome email whenever someone registers a new account on my website.
My problem is, I needed to create a "Create User" page on my admin section. Now every time I create a user from the admin section the email still fires off an email welcoming the new user.
This would be fine, but I need that email to say something else.
I don't want the Welcome email to fire when creating a user from the admin panel.
How can I control this Event from sending the email?
Code pretty much goes in this order:
1. Event code: NewUser.php
namespace App\Events;
... irrelevant classes
use Illuminate\Foundation\Events\Dispatchable;
use App\User;
class NewUser
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user;
public function __construct(User $user)
{
$this->user = $user;
}
}
2. Listener: SendWelcomeEmail.php
namespace App\Listeners;
use App\Events\NewUser;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Mail;
use App\Mail\NewUserWelcome;
class SendWelcomeEmail
{
public function __construct()
{
//
}
public function handle(NewUser $event)
{
Mail::to($event->user->email)->send(new NewUserWelcome($event->user));
}
}
3. Mail: NewUserWelcome.php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\User;
class NewUserWelcome extends Mailable
{
use Queueable, SerializesModels;
public $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function build()
{
return $this->subject('Welcome To The Website')->markdown('emails.user.newuserwelcome');
}
}
4. Markdown email would be next.
#component('mail::message')
# Greetings bla bla bla
5. EventServiceProvider: is making the call like this:
protected $listen = [
'App\Events\NewUser' => [
'App\Listeners\SendWelcomeEmail',
],
];
6. User model I have the following relevant code:
class User extends Authenticatable {
use Notifiable;
protected $dispatchesEvents = [
'created' => Events\NewUser::class
];
In my ADMIN SAVE USER FUNCTION | UserController This is what I'm using to SAVE the New User From Admin Panel: (No Event classes)
use Illuminate\Http\Request;
use App\User;
use Illuminate\Support\Facades\Hash;
class UserController extends Controller
{
public function adminUserStore(Request $request){
$newsupporter = User::create([
'name'=> $request->name,
'email' => $request->email,
'password' => Hash::make($quickpass),
]);
return back()->with('success','The user has been created and a password reset email has been sent to them.');
}
Any help would be appreciated, I've been battling this one for quite some time.
You can try by adding a new nullable column for your user model, which would check if the user was added by admin or someone else;
$newsupporter = User::create([
'name'=> $request->name,
'email' => $request->email,
'password' => Hash::make($quickpass),
'added_by' => 'admin',
]);
And then create a check and send email only when the user was not added my admin,
public function handle(NewUser $event)
{
if(!$event->user->added_by == 'admin'){
Mail::to($event->user->email)->send(new NewUserWelcome($event->user));
}
}
Personally I would introduce two events instead of the one. Something along the lines of AccountCreatedByUser and AccountCreatedByAdmin. These events can then be handled by separate listeners, which will send separate e-mails. This will mean you'll have to fire these events manually instead of depending on the built-in created event. This can be done like so:
event(new AccountCreatedByUser($user));
Documentation for firing events manually can be found here

Why is my Laravel Lumen listener being called twice?

My listener is being called twice, but the event is fired only once.
I got the code from Lumen 5.7 example and have no idea where is my mistake.
bootstrap/app.php
$app->register(App\Providers\EventServiceProvider::class);
app/Providers/EventServiceProvider.php
protected $listen = [
'App\Events\NewAuthEvent' => [
'App\Listeners\SendNewAuthListener',
],
];
app/Events/NewAuthEvent.php
use Illuminate\Queue\SerializesModels;
use App\Data\Entity\User;
use App\Data\Entity\Authorization;
use Illuminate\Support\Facades\Log;
class NewAuthEvent
{
use SerializesModels;
public $user;
public $auth;
public function __construct(User $user, Authorization $auth)
{
Log::debug("once :)");
$this->user = $user;
$this->auth = $auth;
}
}
app/Listeners/SendNewAuthListener.php
use App\Events\NewAuthEvent;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Data\Service\MessengerService;
use Illuminate\Support\Facades\Log;
class SendNewAuthListener
{
private $messenger;
public function __construct(MessengerService $messenger)
{
Log::debug("twice :(");
$this->messenger = $messenger;
}
public function handle(NewAuthEvent $event)
{
Log::debug("twice as well :(");
$this->messenger->new($event->user, $event->auth);
}
}
firing the event:
event(new NewAuthEvent($objUser, $objAuthorization));
What am I missing? Is there some other parameter or config to be seted?
Thanks in advance!
I had the same issue. Check your EventsServiceProvider. If your are using a shouldDiscoverEvents method that returns true, removing it may solve your issue. See comment by andnacho here.

How setup laravel-notification-channels/webpush

I have installed https://github.com/laravel-notification-channels/webpush
in my project but when send notifications there are nothing. It doesnt work
This is laravel notifications documentation: https://laravel.com/docs/5.5/notifications
This is my code - I have created a notification:
class AccountApproved extends Notification {
use Queueable;
public function __construct()
{
//
}
public function via($notifiable)
{
return [WebPushChannel::class];
}
public function toArray($notifiable)
{
return [
'title' => 'Hello from Laravel!',
'body' => 'Thank you for using our application.',
'action_url' => 'https://laravel.com',
'created' => Carbon::now()->toIso8601String()
];
}
public function toWebPush($notifiable, $notification)
{
return WebPushMessage::create()
->title('Hello from Laravel!')
->icon('/notification-icon.png')
->body('Thank you for using our application.')
->action('View app', 'view_app');
}}
and I call Notification in my controller:
$when = Carbon::now();
$request->user()->notify((new AccountApproved)->delay($when));
But I Webpush doesnt work. What's wrong?
Make sure you are running queue worker like this:
php artisan queue:work
in command line. Otherwise queued notification won't be sent.
In case it doesn't help look at your error log and verify if there are any errors in there
For the method delay() to work you must add to your Notification implements ShouldQueue
class AccountApproved extends Notification implements ShouldQueue { ... }
and ofc use Illuminate\Contracts\Queue\ShouldQueue; before your class

Categories