How setup laravel-notification-channels/webpush - php

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

Related

Laravel 8 Notification Unit Testing not working: The expected notification was not sent

Context:
Laravel 8.83.18
PHPUnit 9.5.21
PHP 8.1.7
I'm trying to implement (it's my first time) a Unit Test for a use case that sends an email as a Laravel Notification. I am implementing my web app with a Domain-Driven Design approach and, to simplify and debug, I've checked Laravel Official Documentation (https://laravel.com/docs/8.x/mocking#notification-fake), and I am trying to make the simplest case work, but it doesn't (without using my DDD approach that sends the notification through a use case). I will show you my code:
Test Class:
<?php
declare(strict_types=1);
namespace Tests\Unit\Modules\Test;
use App\Models\User\User;
use App\Notifications\TestNotification;
use Illuminate\Support\Facades\Notification;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_orders_can_be_shipped()
{
Notification::fake();
$emil = 'johndoe#domain.com';
$user = new User();
$user->setAttribute('email', $emil);
// Executing notification sending...
Notification::route('mail', $email)->notify(new TestNotification($user));
// Assert a notification was sent to the given users...
Notification::assertSentTo(
[$user], TestNotification::class
);
}
}
Test Notification class:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class TestNotification extends Notification
{
use Queueable;
private $user;
public function __construct($user)
{
$this->$user = $user;
}
public function via($notifiable)
{
return ['mail','database'];
}
public function toMail($notifiable)
{
return (new MailMessage)
->line('The introduction to the notification.')
->action('Notification Action', url('/'))
->line('Thank you for using our application!');
}
public function toArray($notifiable)
{
return [
'some' => 'data'
];
}
}
Error Response:
The expected [App\Notifications\TestNotification] notification was not sent.
Failed asserting that false is true.
/opt/project/vendor/laravel/framework/src/Illuminate/Support/Testing/Fakes/NotificationFake.php:83
/opt/project/vendor/laravel/framework/src/Illuminate/Support/Testing/Fakes/NotificationFake.php:67
/opt/project/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:261
/opt/project/tests/Unit/Modules/Test/ExampleTest.php:27
Of course, if I try to send the notification out of the Unit Test, it works. I'm using this and I receive the email in my Mailhog container.
Route::get('/test-notification', function (){
Notification::route('mail', 'johndoe#domain.com')->notify(new TestNotification(new \App\Models\User\User()));
return 'Notification Sent';
});
So my question is, why the notification is not sent inside Unit Test, because my call it's the same, it does not match with Laravel says in their DOC.
In addition, I wonder if instead of using an instance of a Laravel model the user class, I can use another kind of object, even a Mock, I guess so, as long as I use the Trait "Notifiable". Correct?
Thank you very much

Laravel + Pusher Expected parameter 2 to be an array, string given in live chat

I've been following this blog post by pusher in their official site for building basic chat app with laravel + pusher.
I've followed every step thoroughly according to the blog, I'd search here and there as some details were not mentioned there.
I can send the message between users (save in DB table) but not updating in realtime in users end.
The below is the error message I get when I press send message button:
Here are the snippets from my code file that I have written.
Events/MessageSent.php
use App\User;
use App\Message;
class MessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user;
public $message;
public function __construct(User $user, Message $message)
{
$this->message = $message;
$this->user = $user;
}
public function broadcastOn()
{
return new PrivateChannel('chat');
}
}
Broutes/channels.php
Broadcast::channel('chat', function ($user) {
return Auth::check();
});
web.php
Auth::routes();
Route::get('/', 'ChatsController#index');
Route::get('messages', 'ChatsController#fetchMessages');
Route::post('messages', 'ChatsController#sendMessage');
ChatsController.php
use App\Events\MessageSent;
use App\Message;
use Illuminate\Http\Request;
use Auth;
class ChatsController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
return view('chat');
}
public function fetchMessages()
{
return Message::with('user')->get();
}
public function sendMessage(Request $request)
{
$user = Auth::user();
$message = $user->messages()->create([
'message' => $request->message,
]);
broadcast(new MessageSent($user, $message))->toOthers();
return ['status' => 'Message Sent!'];
}
}
I'm using laravel version 5.5, pusher 6.1.
The blog post is written for laravel 5.4 and pusher 2.6.
Is version difference causing this issue ?
Thanks for the help.
The solution is to downgrade the pusher version.
composer require pusher/pusher-php-server ^4.1
will still be looking for the appropriate answer for latest version.

Laravel - Notification Mail ShouldQueue does't work

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

Receive Notificatoin Pusher + Echo in Laravel

I am trying to receive notification using echo + pusher. I can post to pusher and pusher console receive the event and channel but i can't get this data on laravel. I read many documents, but none of them work for me.
WebNotification Class // Notification file
private $subscription;
public function __construct($data)
{
$this->subscription = $data;
}
public function via($notifiable)
{
return ['database','broadcast'];
}
public function toBroadcast($notifiable)
{
return new BroadcastMessage([
'data' => $this->subscription,
'count' => $notifiable->unreadNotifications->count()
]);
}
Account Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
class account extends Model
{
use Notifiable;
public function receivesBroadcastNotificationsOn()
{
return 'accounts.'.$this->id;
}
}
MyNotification // To call event to send data to pusher
public function DatabaseNot(){
$user = Account::where('id', Cookie::get('uid'))->first();
$data = collect(['title'=>'Hello Title', 'body'=>'my body']);
$user->notify(new WebNotification($data));
return view('layout.test',['user'=>$user]);
}
Pusher log
Channel: private-accounts.23, Event: Illuminate\Notifications\Events\BroadcastNotificationCreated
I call Echo in resorces/js/app.js
Echo.private('App.accounts.23')
.notification((notification) => {
console.log(notification.type);
});
I did not get any response from this.
I already add csrf token in meta, I compiled js code using NPM run watch. I tried many other ways, no one provide clear document, its so confusing.

How to listen messageSent event in laravel 5.5

Hi I am a beginner for events and listeners in laravel. So please explain me how to achieve this :
Aim :
Send an email to user. And know whether email is sent or not.
My Understanding :
Laravel has in-built event Illuminate\Mail\Events\MessageSent to fire after email is sent and I have to write a listener to listen the event.
What I did :
To send email :
Mail::to($receiverAddress)->send(new SendNewUserPassword($content));
This is working fine. Able to send email to user successfully.
To listen messageSent event, I created this listener :
<?php
namespace App\Listeners;
use Illuminate\Mail\Events\MessageSent;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class LogSentMessage
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param MessageSent $event
* #return void
*/
public function handle(MessageSent $event)
{
return $event->message;
}
}
To Register Event :
protected $listen = [
'App\Events\Event' => [
'App\Listeners\EventListener',
],
'Illuminate\Mail\Events\MessageSent' => [
'App\Listeners\LogSentMessage',
],
];
In Controller :
event(new MessageSent())
Please guide me how to return the message handled in Listener from controller. If my above approach is wrong explain me how to achieve it. This I am using for an api, so if sending mail is success/fail I want to know.
You can pass data from the controller to the mailable, and then from the mailable to the listener
For example I have a model called SendOrder that I use to keep track the status of the email, so I pass this model from the controller to the listener
This is what you have to do from scratch
In your controller
Pass the model to your Mailable constructor
$send_order = SendOrder::create(['status' => 'received', 'email' => 'foo#example.com']);
Mail::to($receiverAddress)->send(new SendNewMail($send_order));
In the Mailable SendNewMail
Class Mailable has a method withSwiftMessage() which you can use to store variables/objects that you can access later from the listener.
We will make a constructor that pass the model to the build() method where we can execute the withSwiftMessage() to store it for later.
use App\SendOrder;
class SendNewMail extends Mailable
{
protected $send_order;
public function __construct( SendOrder $send_order )
{
$this->send_order = $send_order;
}
public function build()
{
$send_order = $this->send_order;
$this->withSwiftMessage(function ($message) use($send_order) {
$message->send_order = $send_order;
});
// Do more stuffs
}
}
Create the listener
Register the event and listener in the file app/Providers/EventServiceProvider.php
protected $listen =
'Illuminate\Mail\Events\MessageSent' => [
'App\Listeners\LogSentMessage',
],
];
Now execute the command:
php artisan event:generate
This will automatically generate the new listener app\Listeners\LogSentMessage with a template code that's connected to the built-in event Illuminate\Mail\Events\MessageSent
In your Listener LogSentMessage
You can access the model this way:
public function handle(MessageSent $event)
{
$send_order = $event->message->send_order;
$send_order->update(['status' => 'sent']);
}
In your EventServiceProvider add your event and listener
protected $listen = [
'Illuminate\Notifications\Events\NotificationSent' => [
'App\Listeners\YourListenerClass',
],
];
and in YourListnerClass
public function handle(NotificationSent $event)
{
//access your $event data here
//which includes notification details too
}
Doing php php artisan event:generate will generate App\Listeners\LogSentMessage for you.
Edit the file for example:
public function handle(MessageSent $event)
{
dd($event->message->getBody(), $event->message->toString());
}
I was stuck forever and ever trying to get my EventServiceProvider to register the Illuminate\Mail\MessageSent event to a local listener. Every time that I tried to do
php artisan event:generate
I would get
Your application doesn't have any events matching the given criteria.
I finally found that my EventService provider was using
use Illuminate\Support\ServiceProvider;
when I switched this to use
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
The event was registered properly! Maybe this will help someone.

Categories