Skip to content

Instantly share code, notes, and snippets.

@niisan-tokyo
Last active November 1, 2021 05:07
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save niisan-tokyo/a1a2b4de17d63aa4da174c5961578a55 to your computer and use it in GitHub Desktop.
Save niisan-tokyo/a1a2b4de17d63aa4da174c5961578a55 to your computer and use it in GitHub Desktop.
Ranking class using redis extension
<?php
namespace NiisanTokyo;
/**
* ランキング生成・取得クラス
*
* phpredis エクステンションが必要
*
* @see https://github.com/phpredis/phpredis
*/
class Ranking
{
/** インスタンスの束 */
private static $instances = [];
/** 共通のRedisクライアント */
private static $redis;
/** ランキンググループ */
private $group;
/**
* Rankingオブジェクトのインスタンスの取得
*
* @param string $group ランキンググループ
* @param array $config redis接続コンフィグ
*
* @return Ranking ランキングオブジェクト
*/
public static function getInstance($group, $config = ['host' => 'redis', 'port' => 6379])
{
if (isset(self::$instances[$groupe])) {
return self::$instances[$groupe];
}
if (! isset(self::$redis)) {
self::$redis = new \Redis();
self::$redis->pconnect($config['host'], $config['port']);
}
$obj = new static($group);
self::$instances[$group] = $obj;
return $obj;
}
/**
* スコアをセットする
*
* @param string|int $user_id ユーザーID
* @param int $score スコア
*
* @return boolean
*/
public function setScore($user_id, $score)
{
return self::$redis->zAdd($this->group, $score, $user_id);
}
/**
* ユーザーのランクを取得する
*
* @param string|int $user_id ユーザーID
*
* @return int
*/
public function getRank($user_id)
{
$rank = self::$redis->zRevRank($this->group, $user_id);
if ($rank === false) {
return 0;
}
return $rank + 1;
}
/**
* 指定IDに対するスコアを取得する
*
* @param string|int $user_id ユーザーなどのID
*
* @return int スコア
*/
public function getScore($user_id)
{
return self::$redis->zScore($this->group, $user_id);
}
/**
* ランキング全体のレコード数を取得する
*
* @return int
*/
public function countAll()
{
return self::$redis->zSize($this->group);
}
/**
* 指定されたスコアの範囲にいるユーザー数を取得する
*
* @param int $min スコアの最小値
* @param int $max スコアの最大値
*
* @return int ユーザー数
*/
public function countRange($min, $max)
{
return self::$redis->zCount($min, $max);
}
/**
* 指定IDのスコアを更新する
*
* @param string|int $user_id ユーザーID
* @param int $score スコア
*
* @return boolean
*/
public function updateScore($user_id, $score)
{
return self::$redis->zIncrBy($this->group, $score, $user_id);
}
/**
* ランキングを取得する
*
* 何も指定しない場合は全件取得になる
*
* @param int $start 開始順位
* @param int $limit 取得数
* @param boolean $only_keys キーのみの取得にするかどうか
*
* @return array [<id> => <score>, ...] or [<id>, <id>, ...]
*/
public function getRange($start = 1, $limit = -1, $only_keys = false)
{
$end = ($limit !== -1 ) ? $start + $limit - 2 : $limit;
return self::$redis->zRevRange($this->group, $start - 1, $end, ! $only_keys);
}
/**
* ランキングを削除する
*
* アプリケーションコードには入れてはいけない
*
* @return boolean ランキングの削除が完了したかどうか
*/
public function delete()
{
return self::$redis->delete($this->group);
}
protected function __construct($group)
{
$this->group = $group;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment