I'm using laravel sail to run laravel octane on swoole.
I made a change to my EventServiceProvider:
<?php
namespace App\Providers;
use App\Events\SubscriptionCreated;
use App\Listeners\CreateUserTeam;
use App\Listeners\SendSubscriptionReceipt;
use App\Listeners\UpdateTeamFeatures;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* #var array
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
CreateUserTeam::class
],
SubscriptionCreated::class => [
SendSubscriptionReceipt::class,
UpdateTeamFeatures::class
]
];
/**
* Register any events for your application.
*
* #return void
*/
public function boot()
{
\Log::debug("HERE", $this->listen);
}
}
Here is my listener:
<?php
namespace App\Listeners;
use App\Models\Team;
use Illuminate\Auth\Events\Registered;
class CreateUserTeam
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
\Log::debug("HIT");
}
/**
* Handle the event.
*
* #param Registered $event
* #return void
*/
public function handle(Registered $event)
{
$user = $event->user;
$team = Team::create([
'manager_id' => $user->id,
]);
$team->createAsStripeCustomer();
$user->update(['team_id' => $team->id]);
}
}
No matter what I try this event listener is not being fired. I've tried clearing the cache, composer dump-autoload, php artisan optimize, reloading octane, stopping octane and starting it again. Even stopping the docker containers and starting them again. Nothing works.
It logs the list of listeners (including the CreateUserTeam listener) and it will fire the Email notification but not the other listener.
If anyone has any insight... please. I am at wits-end
I created same situation with you,
Added my listener like you did:
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
TestListener::class,
],
];
Used Laravel's registration test for it:
<?php
namespace Tests\Feature\Auth;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class RegistrationTest extends TestCase
{
use RefreshDatabase;
public function test_registration_screen_can_be_rendered()
{
$response = $this->get('/register');
$response->assertStatus(200);
}
public function test_new_users_can_register()
{
$response = $this->post('/register', [
'name' => 'Test User',
'email' => 'test#example.com',
'password' => 'password',
'password_confirmation' => 'password',
]);
$this->assertAuthenticated();
$response->assertRedirect(RouteServiceProvider::HOME);
}
}
Here is my test listener
<?php
namespace App\Listeners;
use Illuminate\Auth\Events\Registered;
class TestListener
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
\Log::debug("HIT");
dump("test");
}
/**
* Handle the event.
*
* #param object $event
* #return void
*/
public function handle(Registered $event)
{
$user = $event->user;
dump($user->id);
}
}
And run my test inside the sail:
As you can see it runs handle function inside TestListener.php
Can you remove you other code parts inside handle function and try like this? I think you may have some error in your code
Related
I am creating a leave request application for employee in an organization where user can create a leave request and admin(s) can approve/reject the request. The user and admin(s) should receive mail each time after making a leave request and after approval too. I am using event listener to send the mail and could send the mail using separate events and listeners(4 events:
making leave request to admin,
making leave request to user,
after accepting/rejecting the request to admin and
accepting/rejecting the request to user
and likewise 4 listeners too)
but it would be better if I could reduce the number of events and listeners in this case since the user mail and email template only are different.
I studied about event subscribers which subscribe to multiple events from within the subscriber class itself which is not what I want.
Is it possible to send multiple emails to multiple user/admin using less number of events/listeners?
I am using laravel 8
Code:
controller is:
public function store(Request $request)
{
DB::beginTransaction();
try{
$request->validate(
[
'leave_type' => 'in:halfday,fullday',
'start_date' => 'required',
'end_date' => 'required',
'assignee' => 'required',
]
);
$datetime1 = new \DateTime($request->start_date);
$datetime2 = new \DateTime($request->end_date);
$interval = $datetime1->diff($datetime2);
$days = $interval->format('%a');//total requested days
$leave_request= new LeaveRequest();
$leave_request->requested_by = auth()->user()->id;
$leave_request->leave_type_id = $request->leave_type_id ;
$leave_request->leave_type = $request->leave_type;
$leave_request->start_date = $request->start_date;
$leave_request->end_date = $request->end_date;
$leave_request->total_days = $days+1;
$leave_request->assignee = $request->assignee;
$leave_request->reviewer = $request->reviewer;
if($leave_request->save()){
$user = User::where('id', auth()->user()->id)->first();
$assignee = User::where('id',$request->assignee)->first();
$assignee->locale = App::currentLocale();
$assignee->requested_by = $user->name;
event(new SendLeaveRequestToAdminEvent($assignee));//send mail to admin asignee
if($request->reviewer !=null){
$reviewer = User::where('id',$request->reviewer)->first();
$reviewer->locale = App::currentLocale();
$reviewer->requested_by = $user->name;
event(new SendLeaveRequestToAdminEvent($reviewer));//send mail to admin reviewer(optional)
}
$user->locale = App::currentLocale();
event(new SendLeaveRequestToUserEvent($user));//send mail to user
DB::commit();
return response()->json([
'message'=> 'Leave requested successfully',
'status_code' => 200,
]);
}
else{
DB::rollback();
return response()->json([
'status_code' => '204',
'message' => 'Leave request failed',
]);
}
} catch (Exception $error) {
DB::rollback();
return response()->json([
'message' => 'Leave request failed',
'error' => $error
]);
}
}
first event to mail to admin(s) i.e; assignee and reviewer after sending leave request is
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Models\User;
class SendLeaveRequestToAdminEvent
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $admin;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(User $admin)
{
$this->admin = $admin;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
second event to mail to user after sending leave request is
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Models\User;
class SendLeaveRequestToUserEvent
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
first listener to admin(s):
<?php
namespace App\Listeners;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Mail;
use App\Mail\LeaveRequestAdmin;
use App\Events\SendLeaveRequestToAdminEvent;
class SendLeaveRequestToAdminListener
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param SendLeaveRequestToAdminEvent $event
* #return void
*/
public function handle(SendLeaveRequestToAdminEvent $event)
{
$email = $event->admin->email;
Mail::to($email)->locale($event->admin->locale)->send(new LeaveRequestAdmin($event->admin));
}
}
second listener to user:
<?php
namespace App\Listeners;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Mail;
use App\Mail\LeaveRequestUser;
use App\Events\SendLeaveRequestToUserEvent;
class SendLeaveRequestToUserListener
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param SendLeaveRequestToUserEvent $event
* #return void
*/
public function handle(SendLeaveRequestToUserEvent $event)
{
$email = $event->user->email;
Mail::to($email)->locale($event->user->locale)->send(new LeaveRequestUser($event->user));
}
}
mail to admin:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\URL;
class LeaveRequestAdmin extends Mailable
{
use Queueable, SerializesModels;
public $admin;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($admin)
{
$this->admin = $admin;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->markdown('email.leaverequestadmin', [
'url' => URL::to('/home'),
'admin' => $this->admin,
])->subject('Incoming Leave Request');
}
}
mail to user:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\URL;
class LeaveRequestUser extends Mailable
{
use Queueable, SerializesModels;
public $user;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($user)
{
$this->user = $user;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->markdown('email.leaverequestuser', [
'url' => URL::to('/home'),
'user' => $this->user,
])->subject('Leave Request Received');
}
}
the above code is used after leave request is created which have two separate events/listeners/mail/ blade templates. Like wise I have similar another two events/listeners/mail/ blade templates each which are used after the leave request is accepted/rejected.
I am firing some built-in events from my controller. But no events are being (listened and) responded. I have followed this doc to setup password reset functionality, but the \Illuminate\Auth\Events\PasswordReset event is not working. My expectation is that it should send the confirmation email. Below are the codes I have:
routes/web.php:
//...
Route::get('/reset-password/{token}', [AuthController::class, 'reset'])->middleware('guest')->name('password.reset');
Route::post('/reset-password', [AuthController::class, 'shiny'])->middleware('guest')->name('password.update');
app/Http/Controllers/AuthController.php:
//...
public function reset(string $token): View
{
return view('auth/password/reset', ['token' => $token]);
}
public function shiny(ResetUserRequest $request): RedirectResponse
{
$status = Password::reset(
$request->only('email', 'password', 'password_confirmation', 'token'),
function ($user, $password) use ($request) {
$user->forceFill(['password' => $password])->save();
if (!empty($user->getRememberToken())) {
$user->setRememberToken(Str::random(60));
}
event(new PasswordReset($user)); // not working
}
);
if ($status !== Password::PASSWORD_RESET) {
return back()->withErrors(['email' => __($status)]);
}
return redirect()->route('auth.signin')->with('status', __($status));
}
But only one event is being responded: \Illuminate\Auth\Events\Registered. No other event is being responded. I suspect this is happening because no listeners are provided for other events (except for that one) in \App\Providers\EventServiceProvider provider. This is what I got when I scaffolded the project:
namespace App\Providers;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* #var array
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
// no more listeners for other types of events
// could this be the reason?
];
/**
* Register any events for your application.
*
* #return void
*/
public function boot()
{
//
}
}
I'm basically a JS developer, so this all seems complicated to me. Client specifically asked me to do it using Laravel, so that's the problem. Can someone help me out?
no more listeners for other types of events. You should add desired listeners.
could this be the reason? YES.
It would be something like:
namespace App\Providers;
use Illuminate\Auth\Events\PasswordReset; // Pay attention to the namespace
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* #var array
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
PasswordReset::class => [
//Listiners that you need to be called after triggering the PasswordReset event.
]
];
I want to create a first time user login to fill some details , after the user fill some details the second time he login won`t go back to the fill details page,.
So I create a event to update Last_Login_at value Null become 1 so that the user will escape this part.
Am I doing any wrong here?
Events
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class UserHaveStoreTheFormEvent
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user;
/**
* Create a new event instance.
*
* #param $user
*/
public function __construct($user)
{
$this->user = $user;
}
}
Listener
<?php
namespace App\Listeners;
use App\Events\UserHaveStoreTheFormEvent;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class WelcomeNewUser
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param object $event
* #return void
*/
public function handle($event)
{
$user = auth()->user();
$user->last_login_at = 1;
$user->save();
}
}
EventService
<?php
namespace App\Providers;
use App\Events\UserHaveStoreTheFormEvent;
use App\Listeners\WelcomeNewUser;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* #var array
*/
protected $listen = [
[
UserHaveStoreTheFormEvent::class =>[
WelcomeNewUser::class,
],
],
Registered::class => [
SendEmailVerificationNotification::class,
],
];
/**
* Register any events for your application.
*
* #return void
*/
public function boot()
{
parent::boot();
//
}
}
controller
public function store(StoreCustomerRequest $request)
{
$user = Customer::create($request->all());
event(new UserHaveStoreTheFormEvent($user));
return redirect()->route('admin.customers.index');
}
I believe the problem here is EventServiceProvider class. You have defined listeners and events like this:
protected $listen = [
[
UserHaveStoreTheFormEvent::class =>[
WelcomeNewUser::class,
],
],
Registered::class => [
SendEmailVerificationNotification::class,
],
];
and the should look like this:
protected $listen = [
UserHaveStoreTheFormEvent::class =>[
WelcomeNewUser::class,
],
Registered::class => [
SendEmailVerificationNotification::class,
],
];
You wrapped first event with additional array so it's quite possible that's the reason why it's not working fine.
I have created an event-listener that before updating team_members table should save the row to the team_members_log table. Currently, nothing happens no errors no inserts either. I am not sure if the event gets fired at all.
My Model, I am dispatching the event from:
<?php
namespace App\Models;
use App\Events\TeamMemberUpdating;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Model;
class TeamMember extends Model
{
use Notifiable;
protected $table = 'team_members';
protected $fillable = ['project_request_id'];
protected $dispatchesEvents = [
'updating' => TeamMemberUpdating::class,
];
}
The event itself:
<?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;
use App\Models\TeamMember;
class TeamMemberUpdating extends Event
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $teamMember;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(TeamMember $teamMember)
{
$this->teamMember = $teamMember;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
/*public function broadcastOn()
{
return new PrivateChannel('channel-name');
}*/
}
The listener:
<?php
namespace App\Listeners;
use App\Models\TeamMemberLog;
use App\Events\TeamMemberUpdating;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class LogTeamMemberWithProjectRequest
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param TeamMemberUpdating $event
* #return void
*/
public function handle(TeamMemberUpdating $event)
{
TeamMemberLog::create(['name' => $event->teamMember->name, 'title'=> $event->teamMember->title, 'picture' => $event->teamMember->picture, 'email' => $event->teamMember->email, 'phone_number' => $event->teamMember->phonenumber, 'background-information' => $event->teamMemmber->background_information ]);
}
}
registering them:
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
'App\Events\TeamMemberUpdating' => [
'App\Listeners\LogTeamMemberWithProjectRequest',
],
];
I'm having issue fixing the queue part for Laravel.
I have a contact form which works perfectly. I submit the form and a mail is being sent to me with the input details from the form.
But the issue is that if you do not use the Laravel Queues then the UX is lacking because of the waiting time before the mail is being sent and after getting the success message.
So now I want to implement the queuing part, but im not doing it right. Im still a noob at it...
Here is my controller
KontaktformController.php
<?php
namespace App\Http\Controllers;
use App\Jobs\SendEmailJob;
use Carbon\Carbon;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Session;
use App\Kontaktform;
use Illuminate\Http\Request;
use App\Mail\SendEmailMailable;
class KontaktformController extends Controller
{
public function create()
{
return view('kontakt');
}
public function store(Request $request) {
$this->validate($request, [
'name' => 'required|string',
'mobile' => 'required',
'email' => 'required|email',
'subject' => 'required',
'message' => 'required',
]);
/*
Add mail functionality here.*/
$kontakt = new Kontaktform([
'navn' => $request['name'],
'mobilnr' => $request['mobile'],
'fastnetnr' => $request['landline'],
'mail' => $request['email'],
'emne' => $request['subject'],
'beskrivelse' => $request['message']
]);
$kontakt->save();
//$user['email'] = 'test#test.com';
$job = (new SendEmailJob($request['email']))
->delay(Carbon::now()->addSeconds(3));
dispatch($job);
}
}
SendEmailJob.php
<?php
namespace App\Jobs;
use App\Mail\SendEmailMailable;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Facades\Mail;
class SendEmailJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $user;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct($user)
{
$this->user = $user;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$email = new SendEmailMailable('test#test.dk');
Mail::to('admin#admin.dk')->send($email);
}
}
SendEmailMailable.php
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendEmailMailable extends Mailable
{
use Queueable, SerializesModels;
public $request;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($request)
{
$this->request = $request;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->from('test#test.dk')->view('mail.kontaktform');
}
}
kontaktform.blad.php
{{$request['email']}}
In your kontaktform.blad.php (which should be named kontaktform.blade.php btw), you expect the data to be an array because you try to fetch the index ['email'] though in your SendEmailJob.php in the method handle() you pass your email as a string.
So what you should change it to the following:
$email = new SendEmailMailable(['email' => 'test#test.dk']);
or do the following in the controller & in the job:
Controller:
$job = (new SendEmailJob($request))
->delay(Carbon::now()->addSeconds(3));
Job:
protected $request;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct($request)
{
$this->request = $request;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$mailable = new SendEmailMailable($this->request);
Mail::to('admin#admin.dk')->send($mailable);
}
Now all data from the request is should be available in your blade template.
I found the issue. I didnt pass data from mailable to my blade
public function build()
{
return $this->view( 'mail.kontaktform' )->with( [
'request' => $this->request,
] );
}