search

Home  >  Q&A  >  body text

In Laravel, is it possible to dynamically extend the session time based on the route accessed?

<p>The title pretty much sums up my problem. </p> <p>The company I work for has a Laravel application where the session time on <code>config/session.php</code> is set to expire after <strong>120 minutes</strong> which is Default behavior We don't want to change this value. </p> <p>But the system has a specific feature where the user has to answer a large number of forms/questionnaires,<strong>if the user is slow in typing, it may take more than 3 or 4 hours to complete</strong>Return before submitting Reconsider some answers. </p> <p>The problem is that some users still haven't completed all the questions and the session expiration causes them to lose progress, sometimes they only find out after a few minutes that the session has expired when they switch to the "next page" of questions. We thought about saving the already filled in data, but even if we use AJAX calls to persist the content and save the already filled in sections to the database, having to log in again when answering the form is still a bad user experience since they need to follow it anyway , link to the form page again. We receive a lot of complaints from customers due to session expiration. </p> <p>The best solution is to create some kind of function on <code>FormController.php</code> and when the user enters the form page or some other specific route, we will execute something like <code>session() Operation ->extendSessionInMinutes(360)</code>. I did some research but couldn't find anything similar on the Laravel documentation (please note we are using <code>Laravel 8.1</code>) or Stackoverflow. Read a lot about this topic this week, like a solution about creating a new middleware that provides different session lifecycle based on user role or something like that, but this option didn't work for us. </p> <p>I'm working on a solution that will use a similar solution to add a <strong>new variable</strong> <code>session()->put('time_to_logout' , now()->addHours( 2))</code> to know exactly when the session reaches 2 hours, so I can<strong>set the default of <code>SESSION_LIFETIME</code></strong> Increase the lifetime of the value to 5 hours and add a JS function to check every 30 minutes if logout is required and redirect the user to the logout page, if he is on the form page we will stop the check. </p> <p>But I don't think this is actually a good solution, but I can't seem to think of another solution.Is there a way to accomplish what I want by extending the session time in some way? Or recreate the session without affecting the user (<em>I bet this will mess up the CSRF token on the form</em>) and give it 2 hours while he continues to fill out the form Above times seamlessly recreate the session without noticing any changes? </p> <p>Once a session is created, its expiration time cannot be changed? Is there some kind of PHP library that can help me without changing too much of Laravel's default session related functionality? </p> <p><em>Thanks in advance for any comments. </em></p>
P粉019353247P粉019353247452 days ago624

reply all(1)I'll reply

  • P粉978551081

    P粉9785510812023-09-02 00:13:22

    Yes, it's OK. And you need to do the following -

    1. The session life cycle can only be dynamically changed through middleware. Because changing it via any controller (no middleware) will not change the session value since the session has already been started. So you need a middleware. Like this-
    namespace App\Http\Middleware;
    
    class ChangeSessionValueDynamically
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle($request, $next)
        {
            $lifetime = 1440; /* Minutes*/
            config(['session.lifetime' => $lifetime]); /* Helper function */
            return $next($request);
        }
    }
    1. Afterwards, you need to add the middleware to the $middlewarePriority array in the app/Http/Kernel.php file, which must be executed before Laravel runs its own "StartSession" middleware. Like this-

    Add \App\Http\Middleware\ChangeSessionValueDynamically::class, before \Illuminate\Session\Middleware\StartSession::class,.

    /**
         * The priority-sorted list of middleware.
         *
         * This forces non-global middleware to always be in the given order.
         *
         * @var array
         */
        protected $middlewarePriority = [
         ....
         ....
            \App\Http\Middleware\ChangeSessionValueDynamically::class
            \Illuminate\Session\Middleware\StartSession::class,
         ....
         ....   
        ];
    1. Provide an alias for \App\Http\Middleware\ChangeSessionValueDynamically::class as follows -
    /**
        * The application's route middleware.
        *
        * These middleware may be assigned to groups or used individually.
        *
        * @var array
        */
       protected $routeMiddleware = [
        ....
        ....
           'dynamic_session' => \App\Http\Middleware\ChangeSessionValueDynamically::class,
        ....   
        ....
       ];
    1. Include the middleware in the route as follows -
    A) For Group Routes- 
    Route::group([.., 'middleware' => ['dynamic_session', ..]], function () {
        ..
        Route::get('route_1', ['uses' => 'AbcController@index', 'as' => 'abc.index']);
        ..
    }
    
    B) OR For single Route-
    Route::get('route_1', ['uses' => 'AbcController@index', 'as' => 'abc.index'])->middleware('dynamic_session');

    reply
    0
  • Cancelreply