hyperf 十六 session

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

你可能感兴趣的:(php,php)