Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

daglimioux's avatar

Session Listener

Hi there.

Is there a way to implement a listener for Session creation and Session destroy/expiration? I would like to add some attributes to the Session when it is created and remove some DB data on Session destroy/expiration, because I also want to insert the Session ID in some DB tables fields on creation.

If not, anyway to achieve that? I cannot find anything related in docs or even googling.

Thanks for your time.

Best regards, Diego.

0 likes
9 replies
Snapey's avatar

sessions don't expire in the way you might think. They are checked per request. If the user never comes back then the session is never checked. Each time a user visits there is a random chance that a session cleanup process runs. This just deletes old sessions from the system and could be days or weeks after your visitor left.

1 like
kfirba's avatar

@daglimioux I'm not aware of anything like that built in. Getting expired session is kinda tricky tho. You can easily catch the read/write operation for sessions. I think what you can do here is use a custom session driver which will simply be a decorator. For example, if you use the filesystem for sessions, behind the scenes Laravel is going to use the Illuminate\Session\FileSessionHandler class to handle the session storage. What you can do is either extend that class and stack on some behavior or create a decorator:

class CustomFileSessionHandler extends FileSessionHandler implements SessionHandlerInterface
{
    /**
     * {@inheritdoc}
     */
    public function read($sessionId)
    {
        $value = parent::read($sessionId);

        event('session.read', [$sessionId, $value]);

        return $value;
    }
}

Or using a decorator:

<?php

class CustomFileSessionHandler implements SessionHandlerInterface
{
    protected $handler;

    function __construct($handler)
    {
        $this->handler = $handler;
    }

    public function read($sessionId)
    {
        $value = $this->handler->read($sessionId);

        event('session.read', [$sessionId, $value]);

        return $value;
    }

    public function write($sessionId, $data)
    {
        $this->handler->write($sessionId, $data);

        event('session.write', [$sessionId, $data]);

        return true;
    }

    // keep implementing all of the contract's methods.
}

Once you decide which way to go and you implement one of them, you simply need to tell Laravel to use your new custom session driver. To do so, let's go to the AppServiceProvider and in the boot() method add some code:

Session::extend('my-awesome-new-store', function ($app) {
            // Return implementation of SessionHandlerInterface...
            return new CustomFileSessionHandler(
                new Filesystem, config('session.files'), config('session.lifetime')
            );

            // Do note that if you choose to go for the decorator, we need to pass through the base session handler:
            return new CustomFileSessionHandler(
                new FileSessionHandler(
                    new Filesystem, config('session.files'), config('session.lifetime')
                )
            );
        });

Now in your .env file, specify your new awesome custom session store:

SESSION_DRIVER=my-awesome-new-store

Now all that's left is to add listeners for the events.

daglimioux's avatar

@Snapey , do you think that is better to use DB to store information when user logs in and logs out instead of using sessions?

@kfirba I'm using redis session handler. All the sessions information is stored in redis database. I've been searching for some information about laravel sessions and got a similar conclusion to snapey reply: Sessions gets cleaned randomly and not when user logs out.

My goal is to create an ID of random numbers (12 numbers length), that will be used later, and assign it to a user during the time it is logged in and connected. Is it better to use my configured MySQL to achieve that (a new field for user table, for example) or should I use redis database somehow to keep that information out of the APP data and reduce usage on MySQL? Btw, I'm kinda new to Laravel and I don't know how to handle this properly.

Thanks for your help.

Best regards, Diego.

spekkionu's avatar

If you want to have a listener that listens for when a user logs in or out that is a very different then than when a session is created or destroyed.

Laravel has buit-in events that are fired relating to users logging in or out.

Just add listeners for the Illuminate\Auth\Events\Login and Illuminate\Auth\Events\Logout events in your EventServiceProvider.

https://laravel.com/docs/5.4/authentication#events

daglimioux's avatar

Yeah, thats why I asked if that could be a better way to achieve my goal. Btw, I forgot to say that I'm also trying to authenticate registered users and AUTHORIZED guest users, which are not registered on the APP, only a list of allowed emails that have access (as mentioned here https://laracasts.com/discuss/channels/laravel/user-and-guest-login) and thats why I asked about session listeners.

Thanks for your replies!

Snapey's avatar

but you have to consider how often people actually logout versus just closing their browser or shutting down their device. no logout event fires in such circumstances

daglimioux's avatar

For the browser close I can do an axios (ajax) call to the server with the window.beforeUnload() handler.

For the second one could be a bit more tricky, because I should generate session timeout like functions to know if user is interacting with the server or not and call the logout function, which removes the user generated ID from DB, if max idle time is exceded.

This approach should work better

daglimioux's avatar

@highnoon sorry for the late reply.

I'm using the same socket.io and Redis system! I didn't think about that.

If socket.io connection gets closed, then user is logged out, closed the browser or dropped.

Thank you all for your support and your suggestions. I will take everyone in count and I will give a try to some of them.

Best regards, Diego.

Please or to participate in this conversation.