官网地址: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)]);
}
}