How to create event in Laravel?

In this article we will learn how to create event in Laravel with examples.

Laravel event overview

Laravel events have a straightforward observer pattern implementation. We can subscribe and listen to different events that happen in our application.

The event class contains the information about the event. The event classes are stored in the app/Events directory.
The event listeners get the event instances in the handle method of the event. The listeners are in the app/Listeners directory.

We can learn more about Laravel events and listeners at https://laravel.com/docs/10.x/events.

Now we will try to understand Laravel events through a simple newsletter subscription project.

Create Laravel event

Now we will discuss the steps of simple newsletter subscription project in Laravel.

Steps to create Laravel event

We can create events in Laravel by following the below mentioned steps.

Step 1: Create controller

We can use the following artisan command to create the NewsletterController.

php artisan make:controller NewsletterController

This will create NewsletterController.php controller file in app/Http/Controllers.

Step 2: Modify the controller

Now we will modify the NewsletterController.php file.

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Events\UserSubscribed;
class NewsletterController extends Controller
{
public function index(){
return view('index');
}
public function subscribe(Request $request){
$request->validate([
'email' => 'required|email|unique:newsletters,email'
]);
event(new UserSubscribed($request->email));
return back();
}
}
Step 3: Create model and migration

Now we will create the Newsletter model with migration file using the following artisan command.

php artisan make:model Newsletter -m

The abobe command will create Newsletter.php file in app/Models and <DATE>_create_newsletters_table.php file in database/migrations.

The model – Newsletter.php will be like:

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Newsletter extends Model
{
use HasFactory;
}
Step 4: Modify the migration file

We will modify the migration file – <DATE>_create_newsletters_table.php.

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('newsletters', function (Blueprint $table) {
$table->id();
$table->string('email');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('newsletters');
}
};
Step 5: Run the migration artisan command

Next, we will run the following migration artisan command.

php artisan migrate

This command will create newsletters table in database.

Step 6: Create new routes

We will create two routes to display newsletter form and submit newsletter form in routes/web.php.

<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\NewsletterController;
// Event Listeners
Route::get('/newsletter', [NewsletterController::class, 'index']);
Route::post('/subscribe', [NewsletterController::class, 'subscribe']);
Step 7: Create event

We will create event using the following artisan command.

php artisan make:event UserSubscribed

This command above will create UserSubscribed.php in app/Events.

Step 8: Modify UserSubscribed event

We will modify the newly created UserSubscribed event.

<?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 UserSubscribed
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $email;
public function __construct($email)
{
$this->email = $email;
}
public function broadcastOn(): array
{
return [
new PrivateChannel('channel-name'),
];
}
}
Step 9: Create listener

We will create listener using the following artisan command.

php artisan make:listener EmailOwnerAboutSubscription

This will create a listener class file named EmailOwnerAboutSubscription.php in app/Listeners

Step 10: Modify listener

We will now Modify the newly created EmailOwnerAboutSubscription.php listener class file.

<?php
namespace App\Listeners;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Mail;
use App\Models\Newsletter;
use App\Events\UserSubscribed;
use App\Mail\UserSubscribedMessage;
class EmailOwnerAboutSubscription
{
public function __construct()
{
//
}
public function handle(UserSubscribed $event): void
{
Newsletter::insert(['email'=>$event->email]);
Mail::to($event->email)->send(new UserSubscribedMessage());
}
Step 11: Create Mail class

We will creating a Mail class using the following artisan command.

php artisan make:mail UserSubscribedMessage

This will create the mail class file named UserSubscribedMessage.php in app/Mail folder.

Step 12: Modify the mail class

We will now modify the UserSubscribedMessage.php mail class file.

<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class UserSubscribedMessage extends Mailable
{
use Queueable, SerializesModels;
public function __construct()
{
//
}
public function envelope(): Envelope
{
return new Envelope(
subject: 'User Subscribed Message',
);
}
public function content(): Content
{
return new Content(
view: 'mail.subscribed',
);
}
public function attachments(): array
{
return [];
}
}
Step 13: Create view file for a simple mail content

We will create view subscribed.blade.php view file for a simple mail content in resources/views/mail. The code of the file is as follows.

<h1>User has subscribed.</h1
Step 14: Modify the EventServiceProvider

In this step, we will modify the EventServiceProvider.php file stored in app/Providers directory.

<?php
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;
use App\Events\UserSubscribed;
use App\Listeners\EmailOwnerAboutSubscription;
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
UserSubscribed::class => [
EmailOwnerAboutSubscription::class,
],
];
public function boot(): void
{
//
}
public function shouldDiscoverEvents(): bool
{
return false;
}
}

From the above mentioned code we can see that here we are mapping EmailOwnerAboutSubscription listener class with UserSubscribed event class in $listen property.

Step 15: Create view files for routes

In this step we will create index.blade.php view file resources/views directory for newsletter and subscribe routes.

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Newsletter</title>
</head>
<body class="antialiased">
<h2>Newsletter</h2>
<form action="/subscribe" method="post">
@csrf
<input type="email" id="email" name="email" required="required" />
<button type="submit">Subscribe</button>
</form>
</body>
</html>
Step 16: Browser action

Now, if we browse http://<SITEURL>/newsletter, it will open with an input box and subscribe button.

If we add email to the input field and click on the subscribe button, we will be redirected to http://<SITEURL>/subscribe page.

According to the route declaration, the subscribe method of the NewsletterController class is called and the event function is called and then redirected back to the newsletter page.

As the event is called and thus the listener is in action, email is added to the newsletter table and mail is sent to the user.