• hyperf 十六 session


    官网地址:Hyperf

    一 安装

    1. //安装源码
    2. composer require hyperf/session:v2.0.20
    3. //创建配置
    4. php bin/hyperf.php vendor:publish hyperf/session

     使用redis的话,需要安装redis对应源码。

    二 使用

    设置中间件

    1. #config/autoload/middlewares.php
    2. return [
    3. 'http' => [
    4. ……
    5. \Hyperf\Session\Middleware\SessionMiddleware::class,
    6. ……
    7. ],
    8. ];

     默认设置

    1. return [
    2. 'handler' => Handler\FileHandler::class,//默认文件驱动
    3. //'handler' => Handler\RedisHandler::class,//设置redis驱动
    4. 'options' => [
    5. //'connection' => 'default',
    6. 'connection' => 'test1',
    7. 'path' => BASE_PATH . '/runtime/session',
    8. 'gc_maxlifetime' => 1200,
    9. 'session_name' => 'HYPERF_SESSION_ID',
    10. 'domain' => null,
    11. 'cookie_lifetime' => 5 * 60 * 60,
    12. ],
    13. ];

     session对象注入

    1. class IndexController
    2. {
    3. /**
    4. * @Inject()
    5. * @var \Hyperf\Contract\SessionInterface
    6. */
    7. private $session;
    8. public function index()
    9. {
    10. $this->session->get('foo', $default = null); //获取session中foo值
    11. }
    12. }

    Hyperf\Session\Session方法:

    isValidId(string $id)  判断有效的会话ID

    start() 开始session

    getId() 获取会话ID

    setId(string $id) 设置会话ID

    getName() 获取会话名称

    setName(string $name)  设置会话名称

    invalidate(?int $lifetime = null) 使会话失效,并设置新的session最大时长

    migrate(bool $destroy = false, ?int $lifetime = null)

    会话迁移  $destroy为true则删除现有会话 设置新的会话ID

    save() 保存会话数据

    has(string $name) 判断会话中是否对应变量值

    get(string $name, $default = null)  获取属性值

    set(string $name, $value) 设置属性值

    put($key, $value = null) 在回执中设置新的属性值

    all() 获取会话中全部值

    replace(array $attributes) 设置属性,可替换原属性

    remove(string $name) 删除属性值 调用了forget($keys)底层代码,所以功能一样

    forget($keys) 删除属性值

    clear() 清除会话中的属性

    isStarted() 判断会话是否开启

    token()  获取CSRF令牌值

    regenerateToken() 重新生成CSRF令牌值

    previousUrl() 从会话中获取前一个URL

    setPreviousUrl(string $url) 设置会话中的“前一个”URL

    push(string $key, $value) 将值压入会话数组

    三 原理

    还是从注入开始分析。注入后使用$this->session调用Hyperf\Session\Session方法。

    1. class IndexController
    2. {
    3. /**
    4. * @Inject()
    5. * @var \Hyperf\Contract\SessionInterface
    6. */
    7. private $session;
    8. public function index()
    9. {
    10. $this->session->set('foo', 'bar');
    11. }
    12. }

    其配置文件中 \Hyperf\Contract\SessionInterface指向Hyperf\Session\SessionProxy,而SessionProxy中调用Context::get(SessionInterface::class)获取session对象。

    那么其设置位置又在哪……需要研究下session的中间件。

    Hyperf\Session\Middleware\SessionMiddleware的构造中注入Hyperf\Session\SessionManager和Hyperf\Contract\ConfigInterface,在Hyperf\Dispatcher\AbstractRequestHandler::handleRequest()中调用SessionMiddleware::process()。

    SessionMiddleware::process()中先调用SessionManager::start()再调用SessionManager::end()。

    SessionManager::start()中调用设置会话名并设置并返回Hyperf\Session\Session对象。

    SessionManager::end()中传入Session对象,调用Session::save()方法。Session::save()方法中调用config/autoload/session.php中设置的handler对象调用write()方法写入数据。

    Session中例如set()方法,仅是将数据压入属性,在最后执行写入操作。

    代码如下

    1. #Hyperf\Dispatcher\AbstractRequestHandler
    2. protected function handleRequest($request)
    3. {
    4. if (! isset($this->middlewares[$this->offset]) && ! empty($this->coreHandler)) {
    5. $handler = $this->coreHandler;
    6. } else {
    7. $handler = $this->middlewares[$this->offset];
    8. is_string($handler) && $handler = $this->container->get($handler);
    9. }
    10. if (! method_exists($handler, 'process')) {
    11. throw new InvalidArgumentException(sprintf('Invalid middleware, it has to provide a process() method.'));
    12. }
    13. return $handler->process($request, $this->next());
    14. }
    15. #Hyperf\Session\Middleware\SessionMiddleware
    16. class SessionMiddleware implements MiddlewareInterface
    17. {
    18. public function __construct(SessionManager $sessionManager, ConfigInterface $config)
    19. {
    20. $this->sessionManager = $sessionManager;
    21. $this->config = $config;
    22. }
    23. public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    24. {
    25. if (! $this->isSessionAvailable()) {
    26. return $handler->handle($request);
    27. }
    28. $session = $this->sessionManager->start($request);
    29. try {
    30. $response = $handler->handle($request);
    31. } finally {
    32. $this->storeCurrentUrl($request, $session);
    33. $this->sessionManager->end($session);
    34. }
    35. return $this->addCookieToResponse($request, $response, $session);
    36. }
    37. }
    38. #Hyperf\Session\SessionManager
    39. public function start(ServerRequestInterface $request): SessionInterface
    40. {
    41. $sessionId = $this->parseSessionId($request);
    42. // @TODO Use make() function to create Session object.
    43. $session = new Session($this->getSessionName(), $this->buildSessionHandler(), $sessionId);
    44. if (! $session->start()) {
    45. throw new \RuntimeException('Start session failed.');
    46. }
    47. $this->setSession($session);
    48. return $session;
    49. }
    50. public function end(SessionInterface $session): void
    51. {
    52. $session->save();
    53. }
    54. #Hyperf\Session\Session
    55. class Session implements SessionInterface
    56. {
    57. public function __construct($name, SessionHandlerInterface $handler, $id = null)
    58. {
    59. if (!is_string($id) || !$this->isValidId($id)) {
    60. $id = $this->generateSessionId();
    61. }
    62. $this->setId($id);
    63. $this->setName($name);
    64. $this->handler = $handler;
    65. }
    66. public function save(): void
    67. {
    68. $this->ageFlashData();
    69. $this->handler->write($this->getId(), $this->prepareForStorage(serialize($this->attributes)));
    70. $this->started = false;
    71. }
    72. public function set(string $name, $value): void
    73. {
    74. data_set($this->attributes, $name, $value);
    75. }
    76. public function put($key, $value = null): void
    77. {
    78. if (!is_array($key)) {
    79. $key = [$key => $value];
    80. }
    81. foreach ($key as $arrayKey => $arrayValue) {
    82. Arr::set($this->attributes, $arrayKey, $arrayValue);
    83. }
    84. }
    85. public function remove(string $name)
    86. {
    87. return Arr::pull($this->attributes, $name);
    88. }
    89. public function forget($keys): void
    90. {
    91. Arr::forget($this->attributes, $keys);
    92. }
    93. }
    94. #vendor/hyperf/utils/src/Functions.php
    95. if (!function_exists('data_set')) {
    96. function data_set(&$target, $key, $value, $overwrite = true)
    97. {
    98. ……
    99. }
    100. }
    101. if (!function_exists('data_get')) {
    102. function data_get($target, $key, $default = null)
    103. {
    104. ……
    105. }
    106. }
    107. #Hyperf\Utils\Arr
    108. public static function pull(array &$array, string $key, $default = null)
    109. {
    110. $value = static::get($array, $key, $default);
    111. static::forget($array, $key);
    112. return $value;
    113. }
    114. public static function forget(array &$array, $keys): void
    115. {
    116. $original = &$array;
    117. $keys = (array) $keys;
    118. if (count($keys) === 0) {
    119. return;
    120. }
    121. foreach ($keys as $key) {
    122. // if the exact key exists in the top-level, remove it
    123. if (static::exists($array, $key)) {
    124. unset($array[$key]);
    125. continue;
    126. }
    127. $parts = explode('.', (string) $key);
    128. // clean up before each pass
    129. $array = &$original;
    130. while (count($parts) > 1) {
    131. $part = array_shift($parts);
    132. if (isset($array[$part]) && is_array($array[$part])) {
    133. $array = &$array[$part];
    134. } else {
    135. continue 2;
    136. }
    137. }
    138. unset($array[array_shift($parts)]);
    139. }
    140. }

  • 相关阅读:
    实时聊天系统PHP
    软件开发项目文档系列之一文档综述
    Mybatis的动态SQL和分页
    请大家一定不要像我们公司这样打印log日志
    【无标题】
    Eclipse插件的使用和开发
    前端轻量级数据库mongodb
    正厚干货 | 软件测试面试题库
    JS引擎中的线程,事件循环,上下文
    LVDS 转 MIPI 主桥芯片1 概述 GM8829C
  • 原文地址:https://blog.csdn.net/lsswear/article/details/132804840