You're correct that reliably tracking another user's "logged-in" status in Laravel (or any web app) is tricky, especially since sessions are stateless and browsers can be closed or disconnected without notice. Here are some practical solutions and workarounds:
1. Use a "Lock with Heartbeat" Mechanism
Instead of only storing user_id on the file, also store a locked_at timestamp. When a user enters edit mode, set both fields. Then, use JavaScript (with AJAX) to periodically update the locked_at timestamp (e.g., every 30 seconds) as long as the user is actively editing.
Database Table Example:
files
- id
- name
- content
- locked_by (nullable, user_id)
- locked_at (nullable, timestamp)
When entering edit mode:
// In your controller
$file->locked_by = auth()->id();
$file->locked_at = now();
$file->save();
JavaScript Heartbeat (every 30 seconds):
setInterval(function() {
fetch('/files/123/heartbeat', { method: 'POST', credentials: 'same-origin' });
}, 30000);
Route and Controller:
// web.php
Route::post('/files/{file}/heartbeat', [FileController::class, 'heartbeat']);
// FileController.php
public function heartbeat(File $file)
{
if ($file->locked_by === auth()->id()) {
$file->locked_at = now();
$file->save();
}
return response()->noContent();
}
When another user tries to edit:
- Check if
locked_byis set andlocked_atis within the last X minutes (e.g., 2 minutes). - If so, block editing and show a message.
- If not, allow the new user to take the lock.
if ($file->locked_by && $file->locked_by !== auth()->id()) {
$lockAge = now()->diffInSeconds($file->locked_at);
if ($lockAge < 120) {
// File is locked by another user
return redirect()->back()->with('error', 'File is currently being edited by another user.');
}
// Lock is stale, allow takeover
}
2. Allow "Take Over" After Warning
If a lock is stale (e.g., no heartbeat for 2+ minutes), allow the next user to "take over" the lock, possibly after a warning or confirmation.
3. Why Not Check Session Directly?
Laravel sessions are not designed for cross-user querying. You can't reliably check if another user is "online" or "active" without building a custom tracking system (e.g., updating a last_active_at column on every request). Even then, it's not foolproof.
4. Summary
- Use a lock with a timestamp and heartbeat.
- Consider a short timeout (1-2 minutes) for inactivity.
- Allow users to take over stale locks, with a warning if needed.
- Don't try to check other users' sessions directly; it's unreliable and not supported out of the box.
This approach is common in many collaborative apps and balances user experience with technical limitations.