Set.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. <?php
  2. namespace PhpLife\Frame\Package;
  3. /**
  4. * 使用 redis sorted sets
  5. */
  6. class Set extends \PhpLife\Frame\Package
  7. {
  8. const CONFIG_CLASS = 'Redis\\Core';
  9. const PREFIX = '';
  10. const EXPIRE = 0; // 3 天
  11. /**
  12. * 获取列表,从$start 到 $end,默认获取全部
  13. * 从大到小获取!!
  14. * @param $id
  15. * @param $lastId
  16. * @param $limit
  17. * @return array
  18. */
  19. public static function get($id, $lastId, $limit = 20, $withscores = false)
  20. {
  21. $key = self::getKey($id);
  22. try {
  23. if ($lastId <= 0) {
  24. $options = ($limit > 0) ? array('limit' => array(0, $limit)) : array();
  25. if ($withscores) {
  26. $options['withscores'] = true;
  27. }
  28. $result = self::getConnection()->zRevRangeByScore($key, PHP_INT_MAX, 0, $options);
  29. } else {
  30. if ($withscores) {
  31. $options['withscores'] = true;
  32. }
  33. // 获取$lastId对应的score, 如果没有找到,则返回空
  34. $score = self::getConnection()->zScore($key, $lastId);
  35. if ($score === false) {
  36. return array();
  37. }
  38. if ($limit <= 0) {
  39. $result = self::getConnection()->zRevRangeByScore($key, $score, 0, $options);
  40. if ($result) {
  41. if ($lastId == current($result)) {
  42. array_shift($result);
  43. }
  44. }
  45. } else {
  46. // 排除第一个元素, 多取出一个元素, 然后删除
  47. $limit = $limit + 1;
  48. $options = array('limit' => array(0, $limit));
  49. if ($withscores) {
  50. $options['withscores'] = true;
  51. }
  52. $result = self::getConnection()->zRevRangeByScore($key, $score, 0, $options);
  53. if ($result) {
  54. if ($lastId == current($result)) {
  55. array_shift($result);
  56. } elseif (count($result) >= $limit) {
  57. array_pop($result);
  58. }
  59. }
  60. }
  61. }
  62. } catch (\Exception $ex) {
  63. $result = array();
  64. }
  65. return $result;
  66. }
  67. public static function getsByIndex($id, $lastId, $limit = 20, $withscores = false)
  68. {
  69. $key = self::getKey($id);
  70. try {
  71. if ($lastId <= 0) {
  72. $start = 0;
  73. $stop = $limit-1;
  74. $result = self::getConnection()->zRevRange($key, $start, $stop, $withscores);
  75. } else {
  76. $last_index = self::getConnection()->zRevRank($key, $lastId);
  77. if ($last_index) {
  78. $start = $last_index;
  79. $stop = ($start + $limit);
  80. $result = self::getConnection()->zRevRange($key, $start, $stop, $withscores);
  81. if ($result) {
  82. if ($lastId == current($result)) {
  83. array_shift($result);
  84. }
  85. }
  86. }
  87. }
  88. } catch (\Exception $ex) {
  89. $result = array();
  90. }
  91. return $result;
  92. }
  93. public static function getByPage($id, $page, $limit = 20, $withscores = false)
  94. {
  95. $key = self::getKey($id);
  96. try {
  97. $options = array('limit' => array($page * $limit, $limit));
  98. if ($withscores) {
  99. $options['withscores'] = true;
  100. }
  101. $result = self::getConnection()->zRevRangeByScore($key, PHP_INT_MAX, 0, $options);
  102. } catch (\Exception $ex) {
  103. $result = array();
  104. }
  105. return $result;
  106. }
  107. /**
  108. * 获取所有的ID列表
  109. * @param $id
  110. * @return array
  111. */
  112. public static function getAll($id, $withscores = true)
  113. {
  114. $key = self::getKey($id);
  115. //89de3bf93d9670af:
  116. $options = array();
  117. if ($withscores) {
  118. $options['withscores'] = true;
  119. }
  120. try {
  121. $result = self::getConnection()->zRevRangeByScore($key, PHP_INT_MAX, 0, $options);
  122. } catch (\Exception $ex) {
  123. $result = array();
  124. }
  125. return $result;
  126. }
  127. /**
  128. * 获取 $value 的索引值
  129. */
  130. public static function getIndex($id, $value)
  131. {
  132. $key = self::getKey($id);
  133. try {
  134. $result = self::getConnection(true)->zRank($key, $value);
  135. } catch (\Exception $ex) {
  136. $result = false;
  137. }
  138. return $result;
  139. }
  140. /**
  141. * 添加元素, 注意score相同时可能会有问题, 建议使用 addBatch()
  142. * @param $id
  143. * @param int $score
  144. * @param int $value
  145. * @return bool
  146. */
  147. public static function add($id, $score, $value)
  148. {
  149. $key = self::getKey($id);
  150. try {
  151. $result = self::getConnection(true)->zAdd($key, $score, $value);
  152. // 可选过期
  153. $class = get_called_class();
  154. if ($class::EXPIRE) {
  155. self::getConnection(true)->expire($key, $class::EXPIRE);
  156. }
  157. } catch (\Exception $ex) {
  158. $result = false;
  159. }
  160. return $result;
  161. }
  162. /**
  163. * 批量添加, 重新计算权重
  164. * @param $id
  165. * @param array $data key为列表id,value为score,会重新排序,然后计算score
  166. * @return bool|int
  167. */
  168. public static function addBatch($id, Array $data)
  169. {
  170. asort($data); // 升序排列
  171. $i = 1;
  172. foreach ($data as $k => $score) {
  173. $score = $i * 10000;
  174. self::add($id, $score, $k);
  175. $i++;
  176. }
  177. return true;
  178. }
  179. /**
  180. * 移除元素
  181. * @param $id
  182. * @param int $value
  183. * @return int
  184. */
  185. public static function remove($id, $value)
  186. {
  187. $key = self::getKey($id);
  188. try {
  189. $result = self::getConnection(true)->zDelete($key, $value);
  190. } catch (\Exception $ex) {
  191. $result = false;
  192. }
  193. return $result;
  194. }
  195. /**
  196. * 更新集合内容, 先删除(不判断结果),然后插入
  197. * @param $id
  198. * @param $score
  199. * @param $value
  200. * @return bool|int
  201. */
  202. public static function update($id, $score, $value)
  203. {
  204. self::remove($id, $value);
  205. $result = self::add($id, $score, $value);
  206. return $result;
  207. }
  208. /**
  209. * 移除指定范围内元素
  210. * @param $id
  211. * @param int $start
  212. * @param int $stop
  213. * @return int
  214. */
  215. public static function removeByLex($id, $start, $stop)
  216. {
  217. $key = self::getKey($id);
  218. try {
  219. $result = self::getConnection(true)->zDeleteRangeByRank($key, $start, $stop);
  220. } catch (\Exception $ex) {
  221. $result = false;
  222. }
  223. return $result;
  224. }
  225. /**
  226. * 获取列表长度
  227. * @param $id
  228. * @param int $start
  229. * @param int $end
  230. * @return int
  231. */
  232. public static function count($id, $start = 0, $end = PHP_INT_MAX)
  233. {
  234. $key = self::getKey($id);
  235. try {
  236. $result = self::getConnection(true)->zCount($key, $start, $end);
  237. } catch (\Exception $ex) {
  238. $result = 0;
  239. }
  240. return $result;
  241. }
  242. /**
  243. * 删除
  244. * @param $id
  245. * @return bool
  246. */
  247. public static function delete($id)
  248. {
  249. $key = self::getKey($id);
  250. try {
  251. $result = self::getConnection(true)->delete($key);
  252. } catch (\Exception $ex) {
  253. $result = false;
  254. }
  255. return $result;
  256. }
  257. /**
  258. * 获取连接池
  259. * @param bool $isMaster
  260. * @return \Redis
  261. */
  262. protected static function getConnection($isMaster = false)
  263. {
  264. $class = get_called_class();
  265. $configClass = $class::CONFIG_CLASS;
  266. $redis = new \PhpLife\Frame\Library\Redis($configClass);
  267. $connection = $redis->getConnection($isMaster);
  268. return $connection;
  269. }
  270. }