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

earmsby's avatar

update field on User when authenticating

I'm sure this is ridiculously simple, but I'm having difficulty getting something pretty basic to work. I want to update a field in the Users table (last_login) whenever a user logs in.

Here is the code from my SessionController:

public function store(Request $request)
{

    $attributes=request()->validate([
        'email' => ['required', 'email'],
        'password' => ['required'],
    ]);

    if(!Auth::attempt($attributes)){
        throw ValidationException::withMessages([
            'email' => 'Please enter the correct email & password',
        ]);
    }

    //add date of log in to users table
    $userId=Auth::user()->id;
    $user=User::find($userId);
    $user->update([
        'last_login'=>now()
    ]);

    request()->session()->regenerate(); 

    // redirect
    return redirect('/');
}

The authentication works (as it did before I added the lines for updating the last_login field but the field is not being updated. It's not throwing an error - just not updating. FWIW, I also tried updating the field to a hard coded date '2025-04-24' That didn't work either.

I must be missing something obvious, or maybe there's a better way to do this?

0 likes
4 replies
LaryAI's avatar
LaryAI
AI
Best Answer
Level 58

You're very close! The main issue is likely that the last_login field is not listed in the $fillable property of your User model, so mass assignment is being blocked. Laravel protects against mass assignment vulnerabilities by only allowing fields specified in $fillable (or not guarded by $guarded) to be updated via update().

Here's how to fix it:

1. Add last_login to $fillable in your User model

// app/Models/User.php

class User extends Authenticatable
{
    protected $fillable = [
        'name',
        'email',
        'password',
        'last_login', // <-- Add this line
    ];
}

Alternatively, you can use $guarded = []; if you want to allow all fields to be mass assignable (not recommended for security reasons).


2. (Optional) Use the Authenticated Event (Recommended)

A more "Laravel way" is to listen for the Login event and update the field there. This keeps your controller clean and ensures the field is always updated on login, no matter where login happens.

Create an event listener:

// app/Listeners/UpdateLastLogin.php

namespace App\Listeners;

use Illuminate\Auth\Events\Login;

class UpdateLastLogin
{
    public function handle(Login $event)
    {
        $event->user->update(['last_login' => now()]);
    }
}

Register the listener:

In app/Providers/EventServiceProvider.php:

protected $listen = [
    \Illuminate\Auth\Events\Login::class => [
        \App\Listeners\UpdateLastLogin::class,
    ],
];

Run php artisan event:cache if you cache your events.


3. Your Controller Code (if you want to keep it there)

If you prefer to keep it in your controller, after fixing $fillable, your code should work:

$user = Auth::user();
$user->update([
    'last_login' => now()
]);

Or, even simpler:

Auth::user()->update(['last_login' => now()]);

4. Double-check the database

Make sure the last_login column exists in your users table and is of a datetime/timestamp type.


Summary:

  • Add last_login to $fillable in your User model.
  • (Optional) Use an event listener for a cleaner approach.
  • Make sure the column exists in your database.

Let me know if you have any more questions!

earmsby's avatar

Yes! I forgot to add the field to $fillable. Doh! I knew it was something dumb.

Snapey's avatar

See if this reads better

    auth()->user()->last_login=now():
    auth()->user()->save();

saves a query and does not need the column to be fillable

martinbean's avatar

@earmsby I’d take Lary’s suggestion of doing this in a listener attached to the Authenticated event.

You also don’t need to use the request() helper function when you’re the method is literally getting a request instance injected:

  public function store(Request $request)
  {

-     $attributes=request()->validate([
+     $attributes = $request->validate([
          'email' => ['required', 'email'],
          'password' => ['required'],
      ]);

      if(!Auth::attempt($attributes)){
          throw ValidationException::withMessages([
              'email' => 'Please enter the correct email & password',
          ]);
      }

-     //add date of log in to users table
-     $userId=Auth::user()->id;
-     $user=User::find($userId);
-     $user->update([
-         'last_login'=>now()
-     ]);

-     request()->session()->regenerate(); 
+     $request->session()->regenerate(); 

      // redirect
      return redirect('/');
  }

You also seem to grabbing the ID from a user instance… just to fetch that user again from the database. You don’t need to. You already have a user instance; it’s what you retrieved the ID from the in the first place. But if you use an event listener, then the event will have a user instance that you can update:

public function handle(Authenticated $event)
{
    $event->user->forceFill([
        'last_login' => now(),
    ])->save();
}
1 like

Please or to participate in this conversation.