YunSession.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: dingran
  5. * Date: 2019/2/18
  6. * Time: 下午6:48
  7. */
  8. namespace app\common\helpers;
  9. use Illuminate\Support\Facades\DB;
  10. use Illuminate\Support\Facades\Redis;
  11. define('TIMESTAMP', time());
  12. class YunSession implements \SessionHandlerInterface
  13. {
  14. public static $uniacid;
  15. public static $openid;
  16. public static $expire;
  17. public static function start($uniacid, $openid, $expire = 7200)
  18. {
  19. self::$uniacid = $uniacid;
  20. self::$openid = $openid;
  21. self::$expire = $expire;
  22. $cache_setting = $GLOBALS['_W']['config']['setting'];
  23. if (extension_loaded('memcache') && !empty($cache_setting['memcache']['server']) && !empty($cache_setting['memcache']['session'])) {
  24. self::setHandler('memcache');
  25. } elseif (self::getRedisStatus()) {
  26. self::setHandler('redis');
  27. } else {
  28. self::setHandler('mysql');
  29. }
  30. register_shutdown_function('session_write_close');
  31. session_start();
  32. }
  33. public static function setHandler($type = 'mysql')
  34. {
  35. $classname = "app\common\helpers\YunSession{$type}";
  36. if (class_exists($classname)) {
  37. $sess = new $classname;
  38. }
  39. if (version_compare(PHP_VERSION, '5.5') >= 0) {
  40. session_set_save_handler($sess, true);
  41. } else {
  42. session_set_save_handler(
  43. array(&$sess, 'open'),
  44. array(&$sess, 'close'),
  45. array(&$sess, 'read'),
  46. array(&$sess, 'write'),
  47. array(&$sess, 'destroy'),
  48. array(&$sess, 'gc')
  49. );
  50. }
  51. return true;
  52. }
  53. public function open($save_path, $session_name)
  54. {
  55. return true;
  56. }
  57. public function close()
  58. {
  59. return true;
  60. }
  61. public function read($sessionid)
  62. {
  63. return '';
  64. }
  65. public function write($sessionid, $data)
  66. {
  67. return true;
  68. }
  69. public function destroy($sessionid)
  70. {
  71. return true;
  72. }
  73. public function gc($expire)
  74. {
  75. return true;
  76. }
  77. public static function getRedisStatus()
  78. {
  79. try {
  80. return Redis::ping() == 'PONG';
  81. } catch (\Exception $exception) {
  82. return false;
  83. }
  84. }
  85. }
  86. class YunSessionMemcache extends YunSession
  87. {
  88. protected $session_name;
  89. protected function key($sessionid)
  90. {
  91. return $this->session_name . ':' . $sessionid;
  92. }
  93. public function open($save_path, $session_name)
  94. {
  95. $this->session_name = $session_name;
  96. return true;
  97. }
  98. public function read($sessionid)
  99. {
  100. $row = Redis::hgetall($this->key($sessionid));
  101. if ($row['expiretime'] < TIMESTAMP) {
  102. return '';
  103. }
  104. if (is_array($row) && !empty($row['data'])) {
  105. return $row['data'];
  106. }
  107. return '';
  108. }
  109. public function write($sessionid, $data)
  110. {
  111. if (empty($data) || (!empty($data) && empty($this->chk_member_id_session($data)))) {
  112. $read_data = $this->read($sessionid);
  113. if (!empty($member_data = $this->chk_member_id_session($read_data))) {
  114. $data .= $member_data;
  115. }
  116. }
  117. $row = array();
  118. $row['data'] = $data;
  119. $row['expiretime'] = TIMESTAMP + YunSession::$expire;
  120. $result = Redis::hmset($this->key($sessionid), $row);
  121. Redis::expire($this->key($sessionid), YunSession::$expire);
  122. return $result;
  123. }
  124. public function destroy($sessionid)
  125. {
  126. return Redis::del($this->key($sessionid));
  127. }
  128. public function chk_member_id_session($read_data)
  129. {
  130. $member_data = '';
  131. if (!empty($read_data)) {
  132. preg_match_all('/yunzshop_([\w]+[^|]*|)/', $read_data, $name_matches);
  133. preg_match_all('/(a:[\w]+[^}]*})/', $read_data, $value_matches);
  134. if (!empty($name_matches)) {
  135. foreach ($name_matches[0] as $key => $val) {
  136. if ($val == 'yunzshop_member_id') {
  137. $member_data = $val . '|' . $value_matches[0][$key];
  138. }
  139. }
  140. }
  141. }
  142. return $member_data;
  143. }
  144. }
  145. class YunSessionRedis extends YunSessionMemcache
  146. {
  147. public function __construct()
  148. {
  149. }
  150. public function open($save_path, $session_name)
  151. {
  152. $this->session_name = $session_name;
  153. return true;
  154. }
  155. }
  156. class YunSessionMysql extends YunSession
  157. {
  158. public function open($save_path, $session_name)
  159. {
  160. return true;
  161. }
  162. public function read($sessionid)
  163. {
  164. $sql = 'SELECT * FROM ' . DB::getTablePrefix() . 'core_sessions WHERE `sid`=:sessid AND `expiretime`>:time';
  165. $params = array();
  166. $params[':sessid'] = $sessionid;
  167. $params[':time'] = TIMESTAMP;
  168. $row = DB::selectOne($sql, $params);
  169. if (is_array($row) && !empty($row['data'])) {
  170. return $row['data'];
  171. }
  172. return '';
  173. }
  174. public function write($sessionid, $data)
  175. {
  176. if (empty($data) || (!empty($data) && empty($this->chk_member_id_session($data)))) {
  177. $read_data = $this->read($sessionid);
  178. if (!empty($member_data = $this->chk_member_id_session($read_data))) {
  179. $data .= $member_data;
  180. }
  181. }
  182. $row = array();
  183. $row['sid'] = $sessionid;
  184. $row['uniacid'] = YunSession::$uniacid;
  185. $row['openid'] = YunSession::$openid;
  186. $row['data'] = $data;
  187. $row['expiretime'] = TIMESTAMP + YunSession::$expire;
  188. $sql = 'REPLACE INTO ' . DB::getTablePrefix() . "core_sessions (`sid`, `uniacid`, `openid`, `data`, `expiretime`)
  189. VALUES ('{$row['sid']}', {$row['uniacid']}, '{$row['openid']}', '{$row['data']}', {$row['expiretime']})";
  190. return DB::insert($sql) >= 1;
  191. }
  192. public function destroy($sessionid)
  193. {
  194. $row = array();
  195. $row[':sid'] = $sessionid;
  196. $sql = 'DELETE FROM ' . DB::getTablePrefix() . 'core_sessions WHERE `sid` = :sid';
  197. return DB::delete($sql, $row) == 1;
  198. }
  199. public function gc($expire)
  200. {
  201. $sql = 'DELETE FROM ' . DB::getTablePrefix() . 'core_sessions WHERE `expiretime`<:expire';
  202. return DB::delete($sql, [':expire' => TIMESTAMP]) == 1;
  203. }
  204. private function chk_member_id_session($read_data)
  205. {
  206. $member_data = '';
  207. if (!empty($read_data)) {
  208. preg_match_all('/yunzshop_([\w]+[^|]*|)/', $read_data, $name_matches);
  209. preg_match_all('/(a:[\w]+[^}]*})/', $read_data, $value_matches);
  210. if (!empty($name_matches)) {
  211. foreach ($name_matches[0] as $key => $val) {
  212. if ($val == 'yunzshop_member_id') {
  213. $member_data = $val . '|' . $value_matches[0][$key];
  214. }
  215. }
  216. }
  217. }
  218. return $member_data;
  219. }
  220. }