Last active
November 1, 2021 05:07
-
-
Save niisan-tokyo/a1a2b4de17d63aa4da174c5961578a55 to your computer and use it in GitHub Desktop.
Ranking class using redis extension
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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