Storage.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. <?php
  2. namespace WebIM;
  3. class Storage
  4. {
  5. /**
  6. * @var \redis
  7. */
  8. protected $redis;
  9. const PREFIX = 'webim';
  10. const CUSTOMER = 'customer';
  11. const MERCHANT = 'merchant';
  12. function __construct($config)
  13. {
  14. $this->redis = \Swoole::getInstance()->redis;
  15. //清除操作
  16. $this->clearCache();
  17. $this->config = $config;
  18. }
  19. /**
  20. * redis设置密码
  21. */
  22. function storageAuth(){
  23. $this->redis->auth('byt6gc1w0aed2q7h');
  24. }
  25. /**
  26. * 清除缓存
  27. */
  28. function clearCache(){
  29. $this->redis->delete(self::PREFIX.':online');//在线聊天的clientId
  30. $keys = [
  31. self::CUSTOMER . ':customer_*:merchant_*',//在线客户存入缓存 -- 客户 to 商家
  32. self::MERCHANT . ':customer_*:merchant_*',//在线商家存入缓存 -- 商家 to 客户
  33. self::CUSTOMER . ':chatListClient:*',//客户信息
  34. self::MERCHANT . ':chatListClient:*',//商家信息
  35. self::CUSTOMER . ':chatListOnline:uid_*',//客户打开的所有clientId
  36. self::MERCHANT . ':chatListOnline:mid_*'//商家户打开的所有clientId
  37. ];
  38. foreach ($keys as $key){
  39. $allKeys = $this->redis->keys($key);
  40. foreach ($allKeys as $redisKey){
  41. $this->redis->delete($redisKey);
  42. }
  43. }
  44. }
  45. /**
  46. * 会话保存,保存客户端-用户信息
  47. * @param $client_id
  48. * @param $info
  49. * @param $uid
  50. */
  51. function login($client_id, $info, $uid=0, $chatUid=0, $isCustomer=false)
  52. {
  53. if($uid > 0){
  54. if($isCustomer){
  55. $this->setCustomerC2M($client_id, $uid, $chatUid);
  56. }else{
  57. $this->setMerchantM2C($client_id, $chatUid, $uid);
  58. }
  59. }
  60. $this->redis->set(self::PREFIX . ':client:' . $client_id, json_encode($info));
  61. $this->redis->sAdd(self::PREFIX . ':online', $client_id);
  62. }
  63. /**
  64. * 聊天界面退出
  65. * @param $client_id
  66. */
  67. function logout($client_id)
  68. {
  69. $data = $this->redis->get(self::PREFIX . ':client:' . $client_id);
  70. $userInfo = json_decode($data, true);
  71. $chatUid = $userInfo['chatUid'];
  72. if($userInfo['isCustomer'] == 1){
  73. $this->delCustomerC2M($userInfo['uid'], $chatUid, $client_id);
  74. }else{
  75. $this->delMerchantM2C($chatUid, $userInfo['uid'], $client_id);
  76. }
  77. $this->redis->del(self::PREFIX.':client:'.$client_id);
  78. $this->redis->sRemove(self::PREFIX.':online', $client_id);
  79. }
  80. /**
  81. * 聊天对象列表页登录
  82. * @param $client_id
  83. * @param $info
  84. * @param int $uid
  85. * @param bool $isCustomer
  86. */
  87. function chatListLogin($client_id, $info, $uid=0, $isCustomer=false){
  88. if($isCustomer){
  89. $this->addCustomerChatList($client_id, $uid, $info);
  90. }else{
  91. $this->addMerchantChatList($client_id, $uid, $info);
  92. }
  93. }
  94. /**
  95. * 添加客户聊天clientId
  96. * @param $clientId
  97. * @param $customerId
  98. * @param $info
  99. */
  100. function addCustomerChatList($clientId, $customerId, $info){
  101. $this->redis->set(self::CUSTOMER . ':chatListClient:'.$clientId, json_encode($info));//客户信息
  102. $this->redis->sAdd(self::CUSTOMER . ':chatListOnline:uid_'.$customerId, $clientId);//此客户打开的所有clientId
  103. }
  104. /**
  105. * 获取客户所有聊天clientId
  106. * @param $clientId
  107. * @param $customerId
  108. * @param $info
  109. */
  110. function getCustomerChatListStatus($clientId, $customerId = 0){
  111. if($customerId == 0){
  112. $customer = $this->redis->get(self::CUSTOMER . ':chatListClient:'.$clientId);//获取客户信息
  113. $customer = json_decode($customer, true);
  114. $customerId = $customer['uid'];
  115. }
  116. return $this->redis->sMembers(self::CUSTOMER . ':chatListOnline:uid_'.$customerId);//此客户打开的所有clientId
  117. }
  118. /**
  119. * 添加商家聊天clientId
  120. * @param $clientId
  121. * @param $sjId
  122. * @param $info
  123. */
  124. function addMerchantChatList($clientId, $sjId, $info){
  125. $this->redis->set(self::MERCHANT . ':chatListClient:'.$clientId, json_encode($info));//商家信息
  126. $this->redis->sAdd(self::MERCHANT . ':chatListOnline:mid_'.$sjId, $clientId);//商家户打开的所有clientId
  127. }
  128. /**
  129. * 获取商家信息
  130. * @param $clientId
  131. * @return bool|string
  132. */
  133. function getMerchant($clientId){
  134. $merchant = $this->redis->get(self::MERCHANT . ':chatListClient:'.$clientId);//获取商家信息
  135. return json_decode($merchant, true);
  136. }
  137. /**
  138. * 获取商家所有聊天clientId
  139. * @param $clientId
  140. * @param $sjId
  141. * @param $info
  142. */
  143. function getMerchantChatList($clientId, $sjId = 0){
  144. if($sjId == 0){
  145. $merchant = $this->redis->get(self::MERCHANT . ':chatListClient:'.$clientId);//获取商家信息
  146. $merchant = json_decode($merchant, true);
  147. $sjId = $merchant['uid'];
  148. }
  149. return $this->redis->sMembers(self::MERCHANT . ':chatListOnline:mid_'.$sjId);//商家户打开的所有clientId
  150. }
  151. /**
  152. * 商家聊天对象列表页退出
  153. * @param $client_id
  154. */
  155. function merchantChatListLogout($clientId){
  156. $data = $this->redis->get(self::MERCHANT . ':chatListClient:' . $clientId);
  157. $userInfo = json_decode($data, true);
  158. $sjId = $userInfo['uid'];
  159. $this->redis->del(self::MERCHANT . ':chatListClient:' . $clientId);
  160. $this->redis->sRemove(self::MERCHANT . ':chatListOnline:mid_' . $sjId, $clientId);
  161. }
  162. /**
  163. * 用户在线用户列表
  164. * @return array
  165. */
  166. function getOnlineUsers()
  167. {
  168. return $this->redis->sMembers(self::PREFIX . ':online');
  169. }
  170. /**
  171. * 批量获取用户信息
  172. * @param $users
  173. * @return array
  174. */
  175. function getUsers($users)
  176. {
  177. $keys = array();
  178. $ret = array();
  179. foreach ($users as $v)
  180. {
  181. $keys[] = self::PREFIX . ':client:' . $v;
  182. }
  183. $info = $this->redis->mget($keys);
  184. foreach ($info as $v)
  185. {
  186. $ret[] = json_decode($v, true);
  187. }
  188. return $ret;
  189. }
  190. /**
  191. * 获取单个用户信息
  192. * @param $clientId
  193. * @return bool|mixed
  194. */
  195. function getUser($clientId)
  196. {
  197. $ret = $this->redis->get(self::PREFIX . ':client:' . $clientId);
  198. $info = json_decode($ret, true);
  199. return $info;
  200. }
  201. function exists($clientId)
  202. {
  203. return $this->redis->exists(self::PREFIX . ':client:' . $clientId);
  204. }
  205. function keysExists($key){
  206. return $this->redis->exists($key);
  207. }
  208. function getClient($clientId)
  209. {
  210. $data = $this->redis->get(self::PREFIX . ':client:' . $clientId);
  211. return json_decode($data, true);
  212. }
  213. /**
  214. * 在线客户存入缓存 -- 客户 to 商家
  215. * @param $clientId
  216. * @param $customerId
  217. * @param $sjId
  218. */
  219. function setCustomerC2M($clientId, $customerId, $sjId){
  220. //$this->redis->set(self::CUSTOMER . ':customer_'.$customerId.':merchant_' . $sjId, $clientId);
  221. $this->redis->sAdd(self::CUSTOMER . ':customer_'.$customerId.':merchant_' . $sjId, $clientId);
  222. }
  223. /**
  224. * 获取在线客户的clientIds -- 客户 to 商家
  225. * @param $clientId
  226. * @param $customerId
  227. * @param $sjId
  228. */
  229. function getCustomerC2M($customerId, $sjId){
  230. //return $this->redis->get(self::CUSTOMER . ':customer_'.$customerId.':merchant_' . $sjId);
  231. return $this->redis->sMembers(self::CUSTOMER . ':customer_'.$customerId.':merchant_' . $sjId);
  232. }
  233. /**
  234. * 删除客户缓存 -- 客户 to 商家
  235. * @param $customerId
  236. * @param $sjId
  237. */
  238. function delCustomerC2M($customerId, $sjId, $clientId){
  239. //$this->redis->del(self::CUSTOMER . ':customer_'.$customerId.':merchant_' . $sjId);
  240. $this->redis->sRemove(self::CUSTOMER . ':customer_'.$customerId.':merchant_' . $sjId, $clientId);
  241. }
  242. /**
  243. * 客户在线的客户端数
  244. * @param $customerId
  245. * @param $sjId
  246. * @return int
  247. */
  248. function existCustomerClientC2M($customerId, $sjId){
  249. return $this->redis->sCard(self::CUSTOMER . ':customer_'.$customerId.':merchant_' . $sjId);
  250. }
  251. /**
  252. * 在线商家存入缓存 -- 商家 to 客户
  253. * @param $clientId
  254. * @param $customerId
  255. * @param $sjId
  256. */
  257. function setMerchantM2C($clientId, $customerId, $sjId){
  258. //$this->redis->set(self::MERCHANT . ':customer_'.$customerId.':merchant_' . $sjId, $clientId);
  259. $this->redis->sAdd(self::MERCHANT . ':customer_'.$customerId.':merchant_' . $sjId, $clientId);
  260. }
  261. /**
  262. * 获取在线商家的clientIds -- 商家 to 客户
  263. * @param $clientId
  264. * @param $customerId
  265. * @param $sjId
  266. */
  267. function getMerchantM2C($customerId, $sjId){
  268. //return $this->redis->get(self::MERCHANT . ':customer_'.$customerId.':merchant_' . $sjId);
  269. return $this->redis->sMembers(self::MERCHANT . ':customer_'.$customerId.':merchant_' . $sjId);
  270. }
  271. /**
  272. * 删除商家缓存 -- 商家 to 客户
  273. * @param $customerId
  274. * @param $sjId
  275. */
  276. function delMerchantM2C($customerId, $sjId, $clientId){
  277. //$this->redis->del(self::MERCHANT . ':customer_'.$customerId.':merchant_' . $sjId);
  278. $this->redis->sRemove(self::MERCHANT . ':customer_'.$customerId.':merchant_' . $sjId, $clientId);
  279. }
  280. /**
  281. * 商家在线的客户端数
  282. * @param $customerId
  283. * @param $sjId
  284. * @return int
  285. */
  286. function existMerchantClientC2M($customerId, $sjId){
  287. return $this->redis->sCard(self::MERCHANT . ':customer_'.$customerId.':merchant_' . $sjId);
  288. }
  289. /**
  290. * 记录消息
  291. * @param $userid
  292. * @param $msg
  293. */
  294. function addHistory($userid, $msg)
  295. {
  296. $info = $this->getUser($userid);
  297. $log['user'] = $info;
  298. $log['msg'] = $msg;
  299. $log['time'] = time();
  300. $log['type'] = empty($msg['type']) ? '' : $msg['type'];
  301. $chatLogKey = $info['chatLogKey'];
  302. $isCustomer = $info['isCustomer'];
  303. $role = $isCustomer ? 'customer' : 'merchant';
  304. $now = time();
  305. $this->redis->zAdd($chatLogKey, $now, $now.'{~CHAT~}'.$role.'{~CHAT~}'.$msg);
  306. }
  307. /**
  308. * 直接从参数中取key,记录消息
  309. * @param $data 缓存相关数据
  310. * @param $msg
  311. */
  312. function addHistoryByData($data, $msg)
  313. {
  314. $info = $data;
  315. $chatLogKey = $info['chatLogKey'];
  316. $isCustomer = $info['isCustomer'];
  317. $role = $isCustomer ? 'customer' : 'merchant';
  318. $now = time();
  319. $this->redis->zAdd($chatLogKey, $now, $now.'{~CHAT~}'.$role.'{~CHAT~}'.$msg);
  320. }
  321. function getHistory($clientId, $offset = 0, $num = 100)
  322. {
  323. $userInfo = $this->getUser($clientId);
  324. $chatLogKey = $userInfo['chatLogKey'];
  325. $return = $this->redis->zRange($chatLogKey, 0, -1, 'WITHSCORES');
  326. $conList = [];
  327. if(!empty($return)){
  328. foreach($return as $key => $val){
  329. $time = $val;
  330. $arr = explode('{~CHAT~}', $key);
  331. if(count($arr) == 3){
  332. $createTime = $arr[0];
  333. $msgBelongTo = $arr[1];
  334. $msg = $arr[2];
  335. $conArr = ['msgBelongTo' => $msgBelongTo,'content' => $msg,'createTime' =>$createTime];
  336. $conList[] = $conArr;
  337. }
  338. }
  339. return $conList;
  340. }
  341. return [];
  342. }
  343. /**
  344. * 记录发来新消息的客户
  345. * @param $customerId
  346. * @param $sjId
  347. * @param $time
  348. */
  349. function addMerchantNewChater($customerId, $sjId, $time){
  350. $key = "merchant_{$sjId}_new_msg";
  351. $this->redis->zAdd($key, $time, $customerId);//记录商家的新消息用户有谁
  352. }
  353. /**
  354. * 记录商家聊过天的客户
  355. * @param $customerId
  356. * @param $sjId
  357. * @param $time
  358. */
  359. function addMerchantChaterLog($customerId, $sjId, $time){
  360. $key = "merchant_{$sjId}_history_chat_user";
  361. $this->redis->zAdd($key, $time, $customerId);//记录商家的最近联系人(1商家 对 n客户)
  362. }
  363. /**
  364. * 获取商家与客户的聊天缓存记录
  365. * @param $customerId
  366. * @param $sjId
  367. * @param $time
  368. */
  369. function getMerchantChaterLog($sjId){
  370. $key = "merchant_{$sjId}_new_msg";
  371. $newMsgCustomers = $this->redis->zRange($key, 0, -1, 'WITHSCORES');//商家的新消息用户有谁
  372. $newMsgCustomers = $this->cacheToArray($newMsgCustomers);
  373. $key_2 = "merchant_{$sjId}_history_chat_user";
  374. $historyCustomers = $this->redis->zRange($key_2, 0, -1, 'WITHSCORES');//商家的最近联系人(1商家 对 n客户)
  375. $historyCustomers = $this->cacheToArray($historyCustomers);
  376. return ['newMsgCustomers'=>$newMsgCustomers, 'historyCustomers'=>$historyCustomers];
  377. }
  378. /**
  379. * 移除商家的新消息用户
  380. * @param $customerId
  381. * @param $sjId
  382. */
  383. function remMerchantChater($customerId, $sjId){
  384. $key = "merchant_{$sjId}_new_msg";
  385. $this->redis->zRem($key, $customerId);//移除商家的新消息用户
  386. }
  387. /**
  388. * 获取客户的聊天缓存记录
  389. * @param $customerId
  390. * @param $sjId
  391. * @param $time
  392. */
  393. function addCustomerChaterLog($customerId, $sjId, $time){
  394. }
  395. /**
  396. * 有序集合 转 数组
  397. * @param $cacheData
  398. * @return array
  399. */
  400. function cacheToArray($cacheData){
  401. $array = [];
  402. if(!empty($cacheData) && is_array($cacheData)){
  403. foreach($cacheData as $key => $val){
  404. $array[$val] = $key;
  405. }
  406. }
  407. return $array;
  408. }
  409. /**
  410. * 获取客户用户信息
  411. * @param $key 缓存键
  412. * @return array
  413. */
  414. function getCustomer($key){
  415. $user = $this->redis->hGetAll($key);
  416. return $user;
  417. }
  418. }