Session.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. <?php
  2. /**
  3. * This file is part of workerman.
  4. *
  5. * Licensed under The MIT License
  6. * For full copyright and license information, please see the MIT-LICENSE.txt
  7. * Redistributions of files must retain the above copyright notice.
  8. *
  9. * @author walkor<walkor@workerman.net>
  10. * @copyright walkor<walkor@workerman.net>
  11. * @link http://www.workerman.net/
  12. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  13. */
  14. namespace Workerman\Protocols\Http;
  15. /**
  16. * Class Session
  17. * @package Workerman\Protocols\Http
  18. */
  19. class Session
  20. {
  21. /**
  22. * Session andler class which implements SessionHandlerInterface.
  23. *
  24. * @var string
  25. */
  26. protected static $_handlerClass = 'Workerman\Protocols\Http\Session\FileSessionHandler';
  27. /**
  28. * Parameters of __constructor for session handler class.
  29. *
  30. * @var null
  31. */
  32. protected static $_handlerConfig = null;
  33. /**
  34. * Session.gc_probability
  35. *
  36. * @var int
  37. */
  38. protected static $_sessionGcProbability = 1;
  39. /**
  40. * Session.gc_divisor
  41. *
  42. * @var int
  43. */
  44. protected static $_sessionGcDivisor = 1000;
  45. /**
  46. * Session.gc_maxlifetime
  47. *
  48. * @var int
  49. */
  50. protected static $_sessionGcMaxLifeTime = 1440;
  51. /**
  52. * Session handler instance.
  53. *
  54. * @var \SessionHandlerInterface
  55. */
  56. protected static $_handler = null;
  57. /**
  58. * Session data.
  59. *
  60. * @var array
  61. */
  62. protected $_data = array();
  63. /**
  64. * Session changed and need to save.
  65. *
  66. * @var bool
  67. */
  68. protected $_needSave = false;
  69. /**
  70. * Session id.
  71. *
  72. * @var null
  73. */
  74. protected $_sessionId = null;
  75. /**
  76. * Session constructor.
  77. *
  78. * @param string $session_id
  79. */
  80. public function __construct($session_id)
  81. {
  82. static::checkSessionId($session_id);
  83. if (static::$_handler === null) {
  84. static::initHandler();
  85. }
  86. $this->_sessionId = $session_id;
  87. if ($data = static::$_handler->read($session_id)) {
  88. $this->_data = \unserialize($data);
  89. }
  90. }
  91. /**
  92. * Get session id.
  93. *
  94. * @return string
  95. */
  96. public function getId()
  97. {
  98. return $this->_sessionId;
  99. }
  100. /**
  101. * Get session.
  102. *
  103. * @param string $name
  104. * @param mixed|null $default
  105. * @return mixed|null
  106. */
  107. public function get($name, $default = null)
  108. {
  109. return isset($this->_data[$name]) ? $this->_data[$name] : $default;
  110. }
  111. /**
  112. * Store data in the session.
  113. *
  114. * @param string $name
  115. * @param mixed $value
  116. */
  117. public function set($name, $value)
  118. {
  119. $this->_data[$name] = $value;
  120. $this->_needSave = true;
  121. }
  122. /**
  123. * Delete an item from the session.
  124. *
  125. * @param string $name
  126. */
  127. public function delete($name)
  128. {
  129. unset($this->_data[$name]);
  130. $this->_needSave = true;
  131. }
  132. /**
  133. * Retrieve and delete an item from the session.
  134. *
  135. * @param string $name
  136. * @param mixed|null $default
  137. * @return mixed|null
  138. */
  139. public function pull($name, $default = null)
  140. {
  141. $value = $this->get($name, $default);
  142. $this->delete($name);
  143. return $value;
  144. }
  145. /**
  146. * Store data in the session.
  147. *
  148. * @param string $key
  149. * @param mixed|null $value
  150. */
  151. public function put($key, $value = null)
  152. {
  153. if (!\is_array($key)) {
  154. $this->set($key, $value);
  155. return;
  156. }
  157. foreach ($key as $k => $v) {
  158. $this->_data[$k] = $v;
  159. }
  160. $this->_needSave = true;
  161. }
  162. /**
  163. * Remove a piece of data from the session.
  164. *
  165. * @param string $name
  166. */
  167. public function forget($name)
  168. {
  169. if (\is_scalar($name)) {
  170. $this->delete($name);
  171. return;
  172. }
  173. if (\is_array($name)) {
  174. foreach ($name as $key) {
  175. unset($this->_data[$key]);
  176. }
  177. }
  178. $this->_needSave = true;
  179. }
  180. /**
  181. * Retrieve all the data in the session.
  182. *
  183. * @return array
  184. */
  185. public function all()
  186. {
  187. return $this->_data;
  188. }
  189. /**
  190. * Remove all data from the session.
  191. *
  192. * @return void
  193. */
  194. public function flush()
  195. {
  196. $this->_needSave = true;
  197. $this->_data = array();
  198. }
  199. /**
  200. * Determining If An Item Exists In The Session.
  201. *
  202. * @param string $name
  203. * @return bool
  204. */
  205. public function has($name)
  206. {
  207. return isset($this->_data[$name]);
  208. }
  209. /**
  210. * To determine if an item is present in the session, even if its value is null.
  211. *
  212. * @param string $name
  213. * @return bool
  214. */
  215. public function exists($name)
  216. {
  217. return \array_key_exists($name, $this->_data);
  218. }
  219. /**
  220. * Save session to store.
  221. *
  222. * @return void
  223. */
  224. public function save()
  225. {
  226. if ($this->_needSave) {
  227. if (empty($this->_data)) {
  228. static::$_handler->destroy($this->_sessionId);
  229. } else {
  230. static::$_handler->write($this->_sessionId, \serialize($this->_data));
  231. }
  232. }
  233. $this->_needSave = false;
  234. }
  235. /**
  236. * Init.
  237. *
  238. * @return void
  239. */
  240. public static function init()
  241. {
  242. if ($gc_probability = \ini_get('session.gc_probability')) {
  243. self::$_sessionGcProbability = (int)$gc_probability;
  244. }
  245. if ($gc_divisor = \ini_get('session.gc_divisor')) {
  246. self::$_sessionGcDivisor = (int)$gc_divisor;
  247. }
  248. if ($gc_max_life_time = \ini_get('session.gc_maxlifetime')) {
  249. self::$_sessionGcMaxLifeTime = (int)$gc_max_life_time;
  250. }
  251. }
  252. /**
  253. * Set session handler class.
  254. *
  255. * @param mixed|null $class_name
  256. * @param mixed|null $config
  257. * @return string
  258. */
  259. public static function handlerClass($class_name = null, $config = null)
  260. {
  261. if ($class_name) {
  262. static::$_handlerClass = $class_name;
  263. }
  264. if ($config) {
  265. static::$_handlerConfig = $config;
  266. }
  267. return static::$_handlerClass;
  268. }
  269. /**
  270. * Init handler.
  271. *
  272. * @return void
  273. */
  274. protected static function initHandler()
  275. {
  276. if (static::$_handlerConfig === null) {
  277. static::$_handler = new static::$_handlerClass();
  278. } else {
  279. static::$_handler = new static::$_handlerClass(static::$_handlerConfig);
  280. }
  281. }
  282. /**
  283. * Try GC sessions.
  284. *
  285. * @return void
  286. */
  287. public function tryGcSessions()
  288. {
  289. if (\rand(1, static::$_sessionGcDivisor) > static::$_sessionGcProbability) {
  290. return;
  291. }
  292. static::$_handler->gc(static::$_sessionGcMaxLifeTime);
  293. }
  294. /**
  295. * __destruct.
  296. *
  297. * @return void
  298. */
  299. public function __destruct()
  300. {
  301. $this->save();
  302. $this->tryGcSessions();
  303. }
  304. /**
  305. * Check session id.
  306. *
  307. * @param string $session_id
  308. */
  309. protected static function checkSessionId($session_id)
  310. {
  311. if (!\preg_match('/^[a-zA-Z0-9]+$/', $session_id)) {
  312. throw new SessionException("session_id $session_id is invalid");
  313. }
  314. }
  315. }
  316. /**
  317. * Class SessionException
  318. * @package Workerman\Protocols\Http
  319. */
  320. class SessionException extends \RuntimeException
  321. {
  322. }
  323. // Init session.
  324. Session::init();