Skip to content

Instantly share code, notes, and snippets.

@andrey-helldar
Last active May 11, 2018 08:46
Show Gist options
  • Save andrey-helldar/8075cebe07c7e81db6fd74a74c39524a to your computer and use it in GitHub Desktop.
Save andrey-helldar/8075cebe07c7e81db6fd74a74c39524a to your computer and use it in GitHub Desktop.
How many users are online on the current page.
<?php
namespace App\Services;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redis;
/**
* How many users are online on the current page.
*
*
* use App\Services\UsersOnlineService;
*
* class OtherClass
* {
* protected $users_online;
*
* public function __construct(UsersOnlineService $users_online) {
* $this->users_online = $users_online;
* }
*
* public function anyMethod() {
* // Storing information about the current page
* $this->users_online->set();
*
* // Get the number of users on the current page.
* $this->users_online->get();
*
* // Count the number of users on the pages.
* // It is best to perform this function in the cron.
* $this->users_online->count();
* }
* }
*/
class UsersOnlineService
{
/**
* @var string
*/
protected $path = 'stats:online';
/**
* @var string
*/
protected $page;
/**
* @var string
*/
protected $session_id;
/**
* @var int
*/
protected $ttl;
protected $items;
/**
* @param \Illuminate\Http\Request $request
*/
public function __construct(Request $request)
{
if ($request->hasSession()) {
$this->session_id = $request->session()->getId() ?? null;
$this->page = md5($request->url());
}
$this->ttl = now()->addMinutes(5)->timestamp;
$this->items = collect([]);
}
public function set()
{
$key = $this->getKeyName($this->path, 'users', $this->page, $this->session_id);
Redis::connection()->set($key, $this->session_id);
Redis::connection()->expireat($key, $this->ttl);
}
/**
* @return int
*/
public function get()
: int
{
$key = $this->getKeyName($this->path, 'count', $this->page);
return (int) Redis::connection()->get($key) ?: 0;
}
public function count()
{
$name = $this->getKeyName($this->path, 'users', '*');
$keys = Redis::connection()->keys($name);
foreach ($keys as $key) {
$id = explode(':', $key)[3];
$key = $this->getKeyName($this->path, 'count', $id);
$count = $this->getCount($id);
Redis::connection()->set($key, $count);
Redis::connection()->expireat($key, $this->ttl);
}
}
/**
* @param $id
*
* @return int|mixed
*/
private function getCount($id)
{
if ($this->items->has($id)) {
$count = $this->items->get($id) + 1;
}
else {
$count = 1;
}
$this->items->put($id, $count);
return $count;
}
private function getKeyName(...$params)
: string
{
return implode(':', $params);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment