mafortis
mafortis

Reputation: 7138

Laravel online status

I have made custom middleware to track user online status but it has an issue, I can see my own online status but I always see other users as offline while they are not.

Code

Middleware

class UserActivity
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if(Auth::check()){
            $expiresAt = Carbon::now()->addMinute(1);
            Cache::put('user-is-online-' . Auth::user()->id, true, $expiresAt);
        }
        return $next($request);
    }
}

Kernel.php

'web' => [
  //...
  \App\Http\Middleware\UserActivity::class,
],

User.php (model)

public function isOnline()
{
  return Cache::has('user-is-online-' . $this->id);
}

views

@if($user->isOnline())
  Online
@else
  Offline
@endif

Any idea why other users status is always not correct?

PS: I'm open to livewire solution if any :)

Upvotes: 0

Views: 2039

Answers (3)

Clément Baconnier
Clément Baconnier

Reputation: 6108

After digging in the chat we have resolved the issues;

Cache driver issue

Instead of using CACHE_DRIVER=array you have to use CACHE_DRIVER=file

Reason : array is used for testing purpose only and the state will not be persisted in cache between requests.

Livewire key issue

You have use <livewire:my-component key="UNIQUE_ID" /> or <div wire:key="UNIQUE_ID"></div> when the content is inside a foreach or if condition and updated by livewire.

Livewire keeps reference of them to update the DOM. Without, Livewire may update the wrong place.

Upvotes: 1

stillKonfuzed
stillKonfuzed

Reputation: 412

Jquery :

setInterval(()=>{
 $.post('yourUrl.php',{user_id:user_id},(send_online)=>{ console.log(check_online );} );
},200000); //2minutes interval

Php :

if(isset($_POST['user_id'])){
 $user_id = $_POST['user_id']; $current_time = date('d-m-Y g:i:s');
 $query = $con->prepare("Update users set last_online = ? where user_id = ?");
 $query->execute([$current_time,$user_id ]);
}

Checking part (server side php):

$getUser = $con->prepare("Select * from users where user_id = ?");
$getUser->exec....and fetch etc then check
if(timeDiff($Users->last_online) < 2){ echo "is_online";} else{ echo "offline"; } 

Time diff checker function :

function timeDiff($last_online){
 $to_time = strtotime(date('d-m-Y g:i:s'));
 $from_time = strtotime($last_online);
 return round(abs($to_time - $from_time) / 60,2);
}

Upvotes: 0

Gromfer
Gromfer

Reputation: 46

Maybe you should to use database? I do so:

In authizied middleware: app(WriteUserRepository::class)->updateLastActive();

In repository:

 public function updateLastActive()
{
    $this->model = ReadUserRepository::getCurrentUser();
    $this->model->last_active = now();

    return $this->save();
}

UsersOnline scope from User model looks like:

 private const timeToOffline = 120; // seconds

public static function boot()
{
    parent::boot();
    static::addGlobalScope(function ($query) {
        $query->where('last_active', ">", Carbon::now()->subSecond(self::timeToOffline));
    });
}

Then you can get all online users and do what you want with it. If your User model is big you can create only specific query from users repository and select only online users Ids without all information.

Upvotes: 0

Related Questions