Cookie.php 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: liu21st <liu21st@gmail.com>
  10. // +----------------------------------------------------------------------
  11. namespace think;
  12. class Cookie
  13. {
  14. /**
  15. * @var array cookie 设置参数
  16. */
  17. protected static $config = [
  18. 'prefix' => '', // cookie 名称前缀
  19. 'expire' => 0, // cookie 保存时间
  20. 'path' => '/', // cookie 保存路径
  21. 'domain' => '', // cookie 有效域名
  22. 'secure' => false, // cookie 启用安全传输
  23. 'httponly' => false, // httponly 设置
  24. 'setcookie' => true, // 是否使用 setcookie
  25. ];
  26. /**
  27. * @var bool 是否完成初始化了
  28. */
  29. protected static $init;
  30. /**
  31. * Cookie初始化
  32. * @access public
  33. * @param array $config 配置参数
  34. * @return void
  35. */
  36. public static function init(array $config = [])
  37. {
  38. if (empty($config)) {
  39. $config = Config::get('cookie');
  40. }
  41. self::$config = array_merge(self::$config, array_change_key_case($config));
  42. if (!empty(self::$config['httponly'])) {
  43. ini_set('session.cookie_httponly', 1);
  44. }
  45. self::$init = true;
  46. }
  47. /**
  48. * 设置或者获取 cookie 作用域(前缀)
  49. * @access public
  50. * @param string $prefix 前缀
  51. * @return string|
  52. */
  53. public static function prefix($prefix = '')
  54. {
  55. if (empty($prefix)) {
  56. return self::$config['prefix'];
  57. }
  58. return self::$config['prefix'] = $prefix;
  59. }
  60. /**
  61. * Cookie 设置、获取、删除
  62. * @access public
  63. * @param string $name cookie 名称
  64. * @param mixed $value cookie 值
  65. * @param mixed $option 可选参数 可能会是 null|integer|string
  66. * @return void
  67. */
  68. public static function set($name, $value = '', $option = null)
  69. {
  70. //cli模式禁止header输出
  71. if(IS_CLI){
  72. return;
  73. }
  74. !isset(self::$init) && self::init();
  75. // 参数设置(会覆盖黙认设置)
  76. if (!is_null($option)) {
  77. if (is_numeric($option)) {
  78. $option = ['expire' => $option];
  79. } elseif (is_string($option)) {
  80. parse_str($option, $option);
  81. }
  82. $config = array_merge(self::$config, array_change_key_case($option));
  83. } else {
  84. $config = self::$config;
  85. }
  86. $name = $config['prefix'] . $name;
  87. // 设置 cookie
  88. if (is_array($value)) {
  89. array_walk_recursive($value, 'self::jsonFormatProtect', 'encode');
  90. $value = 'think:' . json_encode($value);
  91. }
  92. $expire = !empty($config['expire']) ?
  93. $_SERVER['REQUEST_TIME'] + intval($config['expire']) :
  94. 0;
  95. if ($config['setcookie']) {
  96. setcookie(
  97. $name, $value, $expire, $config['path'], $config['domain'],
  98. $config['secure'], $config['httponly']
  99. );
  100. }
  101. $_COOKIE[$name] = $value;
  102. }
  103. /**
  104. * 永久保存 Cookie 数据
  105. * @access public
  106. * @param string $name cookie 名称
  107. * @param mixed $value cookie 值
  108. * @param mixed $option 可选参数 可能会是 null|integer|string
  109. * @return void
  110. */
  111. public static function forever($name, $value = '', $option = null)
  112. {
  113. if (is_null($option) || is_numeric($option)) {
  114. $option = [];
  115. }
  116. $option['expire'] = 315360000;
  117. self::set($name, $value, $option);
  118. }
  119. /**
  120. * 判断是否有 Cookie 数据
  121. * @access public
  122. * @param string $name cookie 名称
  123. * @param string|null $prefix cookie 前缀
  124. * @return bool
  125. */
  126. public static function has($name, $prefix = null)
  127. {
  128. !isset(self::$init) && self::init();
  129. $prefix = !is_null($prefix) ? $prefix : self::$config['prefix'];
  130. return isset($_COOKIE[$prefix . $name]);
  131. }
  132. /**
  133. * 获取 Cookie 的值
  134. * @access public
  135. * @param string $name cookie 名称
  136. * @param string|null $prefix cookie 前缀
  137. * @return mixed
  138. */
  139. public static function get($name = '', $prefix = null)
  140. {
  141. !isset(self::$init) && self::init();
  142. $prefix = !is_null($prefix) ? $prefix : self::$config['prefix'];
  143. $key = $prefix . $name;
  144. if ('' == $name) {
  145. // 获取全部
  146. if ($prefix) {
  147. $value = [];
  148. foreach ($_COOKIE as $k => $val) {
  149. if (0 === strpos($k, $prefix)) {
  150. $value[$k] = $val;
  151. }
  152. }
  153. } else {
  154. $value = $_COOKIE;
  155. }
  156. } elseif (isset($_COOKIE[$key])) {
  157. $value = $_COOKIE[$key];
  158. if (0 === strpos($value, 'think:')) {
  159. $value = json_decode(substr($value, 6), true);
  160. array_walk_recursive($value, 'self::jsonFormatProtect', 'decode');
  161. }
  162. } else {
  163. $value = null;
  164. }
  165. return $value;
  166. }
  167. /**
  168. * 删除 Cookie
  169. * @access public
  170. * @param string $name cookie 名称
  171. * @param string|null $prefix cookie 前缀
  172. * @return void
  173. */
  174. public static function delete($name, $prefix = null)
  175. {
  176. !isset(self::$init) && self::init();
  177. $config = self::$config;
  178. $prefix = !is_null($prefix) ? $prefix : $config['prefix'];
  179. $name = $prefix . $name;
  180. if ($config['setcookie']) {
  181. setcookie(
  182. $name, '', $_SERVER['REQUEST_TIME'] - 3600, $config['path'],
  183. $config['domain'], $config['secure'], $config['httponly']
  184. );
  185. }
  186. // 删除指定 cookie
  187. unset($_COOKIE[$name]);
  188. }
  189. /**
  190. * 清除指定前缀的所有 cookie
  191. * @access public
  192. * @param string|null $prefix cookie 前缀
  193. * @return void
  194. */
  195. public static function clear($prefix = null)
  196. {
  197. if (empty($_COOKIE)) {
  198. return;
  199. }
  200. !isset(self::$init) && self::init();
  201. // 要删除的 cookie 前缀,不指定则删除 config 设置的指定前缀
  202. $config = self::$config;
  203. $prefix = !is_null($prefix) ? $prefix : $config['prefix'];
  204. if ($prefix) {
  205. foreach ($_COOKIE as $key => $val) {
  206. if (0 === strpos($key, $prefix)) {
  207. if ($config['setcookie']) {
  208. setcookie(
  209. $key, '', $_SERVER['REQUEST_TIME'] - 3600, $config['path'],
  210. $config['domain'], $config['secure'], $config['httponly']
  211. );
  212. }
  213. unset($_COOKIE[$key]);
  214. }
  215. }
  216. }
  217. }
  218. /**
  219. * json 转换时的格式保护
  220. * @access protected
  221. * @param mixed $val 要转换的值
  222. * @param string $key 键名
  223. * @param string $type 转换类别
  224. * @return void
  225. */
  226. protected static function jsonFormatProtect(&$val, $key, $type = 'encode')
  227. {
  228. if (!empty($val) && true !== $val) {
  229. $val = 'decode' == $type ? urldecode($val) : urlencode($val);
  230. }
  231. }
  232. }