Skip to main content

Command Palette

Search for a command to run...

Laravel Events - Listens to a request made to a controller function and writes a log

Updated
4 min read
Laravel Events - Listens to a request made to a controller function and writes a log
M

Mohamad's interest is in Programming (Mobile, Web, Database and Machine Learning). He is studying at the Center For Artificial Intelligence Technology (CAIT), Universiti Kebangsaan Malaysia (UKM).

In Laravel, events are used to broadcast and listen to specific occurrences or actions within your application. Events can be triggered when certain conditions are met, such as when a user registers, when a new order is placed, or when a specific action is performed.

To work with Laravel events, you typically follow these steps:

  1. Create an Event: You start by creating an event class that extends the base Illuminate\Foundation\Events\Event class. This class defines the properties and methods associated with the event. For example, you might create a UserRegistered event class.

  2. Trigger an Event: Next, you trigger the event from the appropriate place in your application. For example, you might trigger the UserRegistered event after a successful user registration process.

  3. Event Listeners: Event listeners are classes that handle the events triggered in your application. You can create event listeners that perform specific actions when an event occurs. For example, you might create a SendWelcomeEmail listener that sends a welcome email to the newly registered user. Listeners can be registered in the EventServiceProvider class.

  4. Binding Listeners to Events: You need to bind the event listeners to their corresponding events. This can be done in the EventServiceProvider class, where you map events to their listeners.

  5. Handling Events: When an event is triggered, Laravel will automatically dispatch the event to its corresponding listeners. The listeners will then handle the event and perform the defined actions.

Laravel's event system provides a convenient way to decouple various components of your application and make it more modular. By using events, you can easily add or remove functionalities without tightly coupling your code.

[1] Register the event and listeners in the EventServiceProvider

Open the EventServiceProvider located in app/Providers/EventServiceProvider.php and add the following code within the $listen array:

<?php

namespace App\Providers;

use App\Events\RequestLogged;
use App\Listeners\LogRequest;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
    protected $listen = [
        RequestLogged::class => [
            LogRequest::class,
        ],
    ];

    // Other code...
}

The statement use App\Events\RequestLogged; and use App\Listeners\LogRequest; provides the information for creating the events and listener classes.

[2] Generate Events and Listener Classes

Run artisan command:

php artisan event:generate

The classes will be created in the respective paths stated in the above step.

[3] Edit Events and Listener Classes

[3.1] Events Class

File: Events/RequestLogged.php

Edit the constructor as follows:

...
    public function __construct(Request $request)
    {
        $this->request = $request;
    }
...

Full code:

<?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 Illuminate\Http\Request;

class RequestLogged
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct(Request $request)
    {
        $this->request = $request;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('channel-name');
    }
}

[3.2] Listener Class

File: Listeners/LogRequest.php

Edit the handler as follows:

...
    public function handle(RequestLogged $event)
    {
        $request = $event->request;

        // Log the request
        Log::info('Request logged:', [
            'method' => $request->method(),
            'url' => $request->fullUrl(),
            'ip' => $request->ip(),
            'user_agent' => $request->userAgent(),
        ]);
    }
...

Full code:

<?php

namespace App\Listeners;

use App\Events\RequestLogged;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;

class LogRequest
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  \App\Events\RequestLogged  $event
     * @return void
     */
    public function handle(RequestLogged $event)
    {
        $request = $event->request;

        // Log the request
        Log::info('Request logged:', [
            'method' => $request->method(),
            'url' => $request->fullUrl(),
            'ip' => $request->ip(),
            'user_agent' => $request->userAgent(),
        ]);
    }
}

[4] Update the triggering class/method

Assuming you have an update method:

use App\Events\RequestLogged;
use Illuminate\Support\Facades\Log;
use DateTime;

...
    public function update(Request $request, $id)
    {
        $validated = $request->validate([
            'name' => 'required|unique:categories|max:50',
            'image'=>'nullable',
        ]);

        $category_updated = Category::where("id", $id)->update($validated);

        /* CODE FOR THIS EXERCISE BEGIN */
        // test event-listener
        event(new RequestLogged($request));
        // test direct logging
        $dt = new DateTime();
        Log::info("Update runs at:".$dt->format('Y-m-d H:i:s'));
        /* CODE FOR THIS EXERCISE END */

        return response()->json(
            [
            'data' => $category_updated, 
            'desc'=>'category_updated',
            'stus' => 'success'
            ]
            );               
    }
...

[5] Observe the outcome

Output: Logs/laravel.log

If data is not sent to log, probably it could be file permission error.

Try changing the file access mode:

chmod -R 755 storage/logs