官网地址:Hyperf
- //安装源码
- composer require hyperf/session:v2.0.20
- //创建配置
- php bin/hyperf.php vendor:publish hyperf/session
使用redis的话,需要安装redis对应源码。
设置中间件
- #config/autoload/middlewares.php
- return [
- 'http' => [
- ……
- \Hyperf\Session\Middleware\SessionMiddleware::class,
- ……
- ],
- ];
默认设置
- return [
- 'handler' => Handler\FileHandler::class,//默认文件驱动
- //'handler' => Handler\RedisHandler::class,//设置redis驱动
- 'options' => [
- //'connection' => 'default',
- 'connection' => 'test1',
- 'path' => BASE_PATH . '/runtime/session',
- 'gc_maxlifetime' => 1200,
- 'session_name' => 'HYPERF_SESSION_ID',
- 'domain' => null,
- 'cookie_lifetime' => 5 * 60 * 60,
- ],
- ];
session对象注入
- class IndexController
- {
-
- /**
- * @Inject()
- * @var \Hyperf\Contract\SessionInterface
- */
- private $session;
-
- public function index()
- {
- $this->session->get('foo', $default = null); //获取session中foo值
- }
-
- }
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方法。
- class IndexController
- {
-
- /**
- * @Inject()
- * @var \Hyperf\Contract\SessionInterface
- */
- private $session;
-
- public function index()
- {
- $this->session->set('foo', 'bar');
- }
-
- }
其配置文件中 \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()方法,仅是将数据压入属性,在最后执行写入操作。
代码如下
- #Hyperf\Dispatcher\AbstractRequestHandler
- protected function handleRequest($request)
- {
- if (! isset($this->middlewares[$this->offset]) && ! empty($this->coreHandler)) {
- $handler = $this->coreHandler;
- } else {
- $handler = $this->middlewares[$this->offset];
- is_string($handler) && $handler = $this->container->get($handler);
- }
- if (! method_exists($handler, 'process')) {
- throw new InvalidArgumentException(sprintf('Invalid middleware, it has to provide a process() method.'));
- }
- return $handler->process($request, $this->next());
- }
-
- #Hyperf\Session\Middleware\SessionMiddleware
- class SessionMiddleware implements MiddlewareInterface
- {
- public function __construct(SessionManager $sessionManager, ConfigInterface $config)
- {
- $this->sessionManager = $sessionManager;
- $this->config = $config;
- }
- public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
- {
- if (! $this->isSessionAvailable()) {
- return $handler->handle($request);
- }
-
- $session = $this->sessionManager->start($request);
-
- try {
- $response = $handler->handle($request);
- } finally {
- $this->storeCurrentUrl($request, $session);
- $this->sessionManager->end($session);
- }
-
- return $this->addCookieToResponse($request, $response, $session);
- }
- }
-
- #Hyperf\Session\SessionManager
- public function start(ServerRequestInterface $request): SessionInterface
- {
- $sessionId = $this->parseSessionId($request);
- // @TODO Use make() function to create Session object.
- $session = new Session($this->getSessionName(), $this->buildSessionHandler(), $sessionId);
- if (! $session->start()) {
- throw new \RuntimeException('Start session failed.');
- }
- $this->setSession($session);
- return $session;
- }
-
- public function end(SessionInterface $session): void
- {
- $session->save();
- }
-
- #Hyperf\Session\Session
- class Session implements SessionInterface
- {
- public function __construct($name, SessionHandlerInterface $handler, $id = null)
- {
- if (!is_string($id) || !$this->isValidId($id)) {
- $id = $this->generateSessionId();
- }
- $this->setId($id);
- $this->setName($name);
- $this->handler = $handler;
- }
- public function save(): void
- {
- $this->ageFlashData();
-
- $this->handler->write($this->getId(), $this->prepareForStorage(serialize($this->attributes)));
-
- $this->started = false;
- }
- public function set(string $name, $value): void
- {
- data_set($this->attributes, $name, $value);
- }
- public function put($key, $value = null): void
- {
- if (!is_array($key)) {
- $key = [$key => $value];
- }
-
- foreach ($key as $arrayKey => $arrayValue) {
- Arr::set($this->attributes, $arrayKey, $arrayValue);
- }
- }
- public function remove(string $name)
- {
- return Arr::pull($this->attributes, $name);
- }
- public function forget($keys): void
- {
- Arr::forget($this->attributes, $keys);
- }
- }
-
- #vendor/hyperf/utils/src/Functions.php
- if (!function_exists('data_set')) {
- function data_set(&$target, $key, $value, $overwrite = true)
- {
- ……
- }
- }
- if (!function_exists('data_get')) {
- function data_get($target, $key, $default = null)
- {
- ……
- }
- }
-
- #Hyperf\Utils\Arr
- public static function pull(array &$array, string $key, $default = null)
- {
- $value = static::get($array, $key, $default);
- static::forget($array, $key);
- return $value;
- }
- public static function forget(array &$array, $keys): void
- {
- $original = &$array;
- $keys = (array) $keys;
- if (count($keys) === 0) {
- return;
- }
- foreach ($keys as $key) {
- // if the exact key exists in the top-level, remove it
- if (static::exists($array, $key)) {
- unset($array[$key]);
- continue;
- }
- $parts = explode('.', (string) $key);
- // clean up before each pass
- $array = &$original;
- while (count($parts) > 1) {
- $part = array_shift($parts);
- if (isset($array[$part]) && is_array($array[$part])) {
- $array = &$array[$part];
- } else {
- continue 2;
- }
- }
- unset($array[array_shift($parts)]);
- }
- }