Session

Testing Is Documentation

tests/Session/SessionTest.phpSession - 图1

QueryPHP 提供了 Session (会话) 可以用于保存用户登录状态。

内置支持的 session 驱动类型包括 file、redis,未来可能增加其他驱动。

使用方式

使用容器 sessions 服务

  1. \App::make('sessions')->set(string $name, $value): void;
  2. \App::make('sessions')->get(string $name, $defaults = null);

依赖注入

  1. class Demo
  2. {
  3. private \Leevel\Session\Manager $session;
  4. public function __construct(\Leevel\Session\Manager $session)
  5. {
  6. $this->session = $session;
  7. }
  8. }

使用静态代理

  1. \Leevel\Session\Proxy\Session::set(string $name, $value): void;
  2. \Leevel\Session\Proxy\Session::get(string $name, $value = null);

session 配置

系统的 session 配置位于应用下面的 option/session.php 文件。

可以定义多个缓存连接,并且支持切换,每一个连接支持驱动设置。

  1. <?php
  2. declare(strict_types=1);
  3. /*
  4. * This file is part of the your app package.
  5. *
  6. * The PHP Application For Code Poem For You.
  7. * (c) 2018-2099 http://yourdomian.com All rights reserved.
  8. *
  9. * For the full copyright and license information, please view the LICENSE
  10. * file that was distributed with this source code.
  11. */
  12. return [
  13. /*
  14. * ---------------------------------------------------------------
  15. * session 驱动
  16. * ---------------------------------------------------------------
  17. *
  18. * 采用什么源保存 session 数据,默认采用文件
  19. */
  20. 'default' => Leevel::env('SESSION_DRIVER', 'file'),
  21. /*
  22. * ---------------------------------------------------------------
  23. * id
  24. * ---------------------------------------------------------------
  25. *
  26. * 相当于 session_id
  27. * null 表示自动生成随机字符串
  28. */
  29. 'id' => null,
  30. /*
  31. * ---------------------------------------------------------------
  32. * name
  33. * ---------------------------------------------------------------
  34. *
  35. * 相当于 session_name
  36. */
  37. 'name' => 'UID',
  38. /*
  39. * ---------------------------------------------------------------
  40. * COOKIE 过期时间
  41. * ---------------------------------------------------------------
  42. *
  43. * SESSION 依赖 COOKIE
  44. * COOKIE 默认过期时间
  45. * 小于等于 0 表示关闭浏览器即失效
  46. */
  47. 'cookie_expire' => 86400,
  48. /*
  49. * ---------------------------------------------------------------
  50. * session 驱动连接参数
  51. * ---------------------------------------------------------------
  52. *
  53. * 这里为所有的 session 驱动的连接参数,每一种不同的驱动拥有不同的配置
  54. * 虽然有不同的驱动,但是在使用上却有着一致性
  55. */
  56. 'connect' => [
  57. 'file' => [
  58. // driver
  59. 'driver' => 'file',
  60. // 文件缓存驱动
  61. 'file_driver' => Leevel::env('SESSION_FILE_DRIVER', 'file_session'),
  62. ],
  63. 'redis' => [
  64. // driver
  65. 'driver' => 'redis',
  66. // Redis 缓存驱动
  67. 'redis_driver' => Leevel::env('SESSION_REDIS_DRIVER', 'redis_session'),
  68. ],
  69. 'test' => [
  70. // driver
  71. 'driver' => 'test',
  72. ],
  73. ],
  74. ];

session 参数根据不同的连接会有所区别,通用的 sesion 参数如下:

配置项配置描述
id相当于 session_id
name相当于 session_name
cookie_expireCOOKIE 过期时间

注意

QueryPHP 并没有使用 PHP 原生 SESSION,而是模拟原生 SESSION 自己实现的一套,使用方法与原生用法几乎一致。与原生 SESSION 不一样的是,QueryPHP 会在最后通过 session 中间件统一写入。

Uses

  1. <?php
  2. use Leevel\Cache\File as CacheFile;
  3. use Leevel\Filesystem\Helper;
  4. use Leevel\Session\File;
  5. use Leevel\Session\ISession;

session 基本使用

session 的使用方法和原生差不多。

设置 session

  1. set(string $name, $value): void;

是否存在 session

  1. has(string $name): bool;

删除 session

  1. delete(string $name): void;
  1. public function testBaseUse(): void
  2. {
  3. $session = $this->createFileSessionHandler();
  4. $this->assertInstanceof(ISession::class, $session);
  5. $this->assertFalse($session->isStart());
  6. $this->assertSame('', $session->getId());
  7. $this->assertSame('UID', $session->getName());
  8. $session->start();
  9. $this->assertTrue($session->isStart());
  10. $session->set('hello', 'world');
  11. $this->assertSame(['hello' => 'world'], $session->all());
  12. $this->assertTrue($session->has('hello'));
  13. $this->assertSame('world', $session->get('hello'));
  14. $session->delete('hello');
  15. $this->assertSame([], $session->all());
  16. $this->assertFalse($session->has('hello'));
  17. $this->assertNull($session->get('hello'));
  18. $session->start();
  19. $this->assertTrue($session->isStart());
  20. $this->assertTrue($session->open('foo', 'bar'));
  21. $this->assertTrue($session->close());
  22. $this->assertTrue($session->destroy('foo'));
  23. $this->assertSame(0, $session->gc(500));
  24. }

setExpire 设置过期时间

过期时间规则如下:

  • null 表示默认 session 缓存时间
  • 小与等于 0 表示永久缓存
  • 其它表示缓存多少时间,单位秒
  1. public function testSetExpire(): void
  2. {
  3. $session = $this->createFileSessionHandler();
  4. $session->setExpire(50);
  5. $session->set('hello', 'world');
  6. $this->assertSame(['hello' => 'world'], $session->all());
  7. $session->start();
  8. $session->save();
  9. $sessionId = $session->getId();
  10. $dirPath = __DIR__.'/cache';
  11. $filePath = $dirPath.'/'.$sessionId.'.php';
  12. $this->assertFileExists($filePath);
  13. $this->assertStringContainsString('[50,', file_get_contents($filePath));
  14. }

put 批量插入

  1. public function testPut(): void
  2. {
  3. $session = $this->createFileSessionHandler();
  4. $session->put('hello', 'world');
  5. $this->assertSame(['hello' => 'world'], $session->all());
  6. $session->put(['foo' => 'bar']);
  7. $this->assertSame(['hello' => 'world', 'foo' => 'bar'], $session->all());
  8. $session->put(['foo' => 'bar']);
  9. $this->assertSame(['hello' => 'world', 'foo' => 'bar'], $session->all());
  10. }

clear 清空 session

  1. public function testClear(): void
  2. {
  3. $session = $this->createFileSessionHandler();
  4. $session->set('hello', ['sub' => 'me', 'foo' => 'bar', 'hello' => 'world']);
  5. $this->assertSame(['hello' => ['sub' => 'me', 'foo' => 'bar', 'hello' => 'world']], $session->all());
  6. $session->clear();
  7. $this->assertSame([], $session->all());
  8. }

flash 闪存一个数据,当前请求和下一个请求可用

  1. public function testFlash(): void
  2. {
  3. $session = $this->createFileSessionHandler();
  4. $session->flash('hello', 'world');
  5. $flash = <<<'eot'
  6. {
  7. "flash.data.hello": "world",
  8. "flash.new.key": [
  9. "hello"
  10. ],
  11. "flash.old.key": []
  12. }
  13. eot;
  14. $this->assertSame(
  15. $flash,
  16. $this->varJson(
  17. $session->all()
  18. )
  19. );
  20. $session->flash('foo', ['bar']);
  21. $flash = <<<'eot'
  22. {
  23. "flash.data.hello": "world",
  24. "flash.new.key": [
  25. "hello",
  26. "foo"
  27. ],
  28. "flash.old.key": [],
  29. "flash.data.foo": [
  30. "bar"
  31. ]
  32. }
  33. eot;
  34. $this->assertSame(
  35. $flash,
  36. $this->varJson(
  37. $session->all()
  38. )
  39. );
  40. }

flashs 批量闪存数据,当前请求和下一个请求可用

  1. public function testFlashs(): void
  2. {
  3. $session = $this->createFileSessionHandler();
  4. $session->flashs(['hello' => 'world', 'foo' => 'bar']);
  5. $flash = <<<'eot'
  6. {
  7. "flash.data.hello": "world",
  8. "flash.new.key": [
  9. "hello",
  10. "foo"
  11. ],
  12. "flash.old.key": [],
  13. "flash.data.foo": "bar"
  14. }
  15. eot;
  16. $this->assertSame(
  17. $flash,
  18. $this->varJson(
  19. $session->all()
  20. )
  21. );
  22. }

nowFlash 闪存一个 flash 用于当前请求使用,下一个请求将无法获取

  1. public function testNowFlash(): void
  2. {
  3. $session = $this->createFileSessionHandler();
  4. $session->nowFlash('hello', 'world');
  5. $flash = <<<'eot'
  6. {
  7. "flash.data.hello": "world",
  8. "flash.old.key": [
  9. "hello"
  10. ]
  11. }
  12. eot;
  13. $this->assertSame(
  14. $flash,
  15. $this->varJson(
  16. $session->all()
  17. )
  18. );
  19. }

nowFlashs 批量闪存数据,用于当前请求使用,下一个请求将无法获取

  1. public function testNowFlashs(): void
  2. {
  3. $session = $this->createFileSessionHandler();
  4. $session->nowFlashs(['hello' => 'world', 'foo' => 'bar']);
  5. $flash = <<<'eot'
  6. {
  7. "flash.data.hello": "world",
  8. "flash.old.key": [
  9. "hello",
  10. "foo"
  11. ],
  12. "flash.data.foo": "bar"
  13. }
  14. eot;
  15. $this->assertSame(
  16. $flash,
  17. $this->varJson(
  18. $session->all()
  19. )
  20. );
  21. }

rebuildFlash 保持所有闪存数据

  1. public function testRebuildFlash(): void
  2. {
  3. $session = $this->createFileSessionHandler();
  4. $session->nowFlashs(['hello' => 'world', 'foo' => 'bar']);
  5. $flash = <<<'eot'
  6. {
  7. "flash.data.hello": "world",
  8. "flash.old.key": [
  9. "hello",
  10. "foo"
  11. ],
  12. "flash.data.foo": "bar"
  13. }
  14. eot;
  15. $this->assertSame(
  16. $flash,
  17. $this->varJson(
  18. $session->all()
  19. )
  20. );
  21. $session->rebuildFlash();
  22. $flash = <<<'eot'
  23. {
  24. "flash.data.hello": "world",
  25. "flash.old.key": [],
  26. "flash.data.foo": "bar",
  27. "flash.new.key": [
  28. "hello",
  29. "foo"
  30. ]
  31. }
  32. eot;
  33. $this->assertSame(
  34. $flash,
  35. $this->varJson(
  36. $session->all()
  37. )
  38. );
  39. }

keepFlash 保持闪存数据

  1. public function testKeepFlash(): void
  2. {
  3. $session = $this->createFileSessionHandler();
  4. $session->nowFlashs(['hello' => 'world', 'foo' => 'bar']);
  5. $flash = <<<'eot'
  6. {
  7. "flash.data.hello": "world",
  8. "flash.old.key": [
  9. "hello",
  10. "foo"
  11. ],
  12. "flash.data.foo": "bar"
  13. }
  14. eot;
  15. $this->assertSame(
  16. $flash,
  17. $this->varJson(
  18. $session->all()
  19. )
  20. );
  21. $session->keepFlash(['hello', 'foo']);
  22. $flash = <<<'eot'
  23. {
  24. "flash.data.hello": "world",
  25. "flash.old.key": [],
  26. "flash.data.foo": "bar",
  27. "flash.new.key": [
  28. "hello",
  29. "foo"
  30. ]
  31. }
  32. eot;
  33. $this->assertSame(
  34. $flash,
  35. $this->varJson(
  36. $session->all()
  37. )
  38. );
  39. }

getFlash 返回闪存数据

  1. public function testGetFlash(): void
  2. {
  3. $session = $this->createFileSessionHandler();
  4. $session->nowFlashs(['hello' => 'world', 'foo' => 'bar']);
  5. $this->assertSame('world', $session->getFlash('hello'));
  6. $this->assertSame('bar', $session->getFlash('foo'));
  7. $session->flash('test', ['foo', 'bar']);
  8. $this->assertSame(['foo', 'bar'], $session->getFlash('test'));
  9. $this->assertNull($session->getFlash('notFound'));
  10. $session->flash('bar', ['sub' => ['foo' => 'bar']]);
  11. $this->assertSame(['foo', 'bar'], $session->getFlash('test'));
  12. $this->assertNull($session->getFlash('test\\notFound'));
  13. }

clearFlash 清理所有闪存数据

  1. public function testClearFlash(): void
  2. {
  3. $session = $this->createFileSessionHandler();
  4. $session->flashs(['hello' => 'world', 'foo' => 'bar']);
  5. $flash = <<<'eot'
  6. {
  7. "flash.data.hello": "world",
  8. "flash.new.key": [
  9. "hello",
  10. "foo"
  11. ],
  12. "flash.old.key": [],
  13. "flash.data.foo": "bar"
  14. }
  15. eot;
  16. $this->assertSame(
  17. $flash,
  18. $this->varJson(
  19. $session->all()
  20. )
  21. );
  22. $session->clearFlash();
  23. $flash = <<<'eot'
  24. {
  25. "flash.new.key": [],
  26. "flash.old.key": [
  27. "hello",
  28. "foo"
  29. ]
  30. }
  31. eot;
  32. $this->assertSame(
  33. $flash,
  34. $this->varJson(
  35. $session->all()
  36. )
  37. );
  38. }

setPrevUrl.prevUrl 设置和返回前一个请求地址

  1. public function testPrevUrl(): void
  2. {
  3. $session = $this->createFileSessionHandler();
  4. $this->assertNull($session->prevUrl());
  5. $session->setPrevUrl('foo');
  6. $this->assertSame('foo', $session->prevUrl());
  7. }

destroySession 终止会话

  1. public function testDestroy(): void
  2. {
  3. $session = $this->createFileSessionHandler();
  4. $this->assertFalse($session->isStart());
  5. $this->assertSame('', $session->getId());
  6. $this->assertSame('UID', $session->getName());
  7. $session->start();
  8. $this->assertTrue($session->isStart());
  9. $this->assertNotNull($session->getId());
  10. $this->assertNotNull($session->getName());
  11. $session->destroySession();
  12. $this->assertFalse($session->isStart());
  13. $this->assertSame('', $session->getId());
  14. $this->assertSame('UID', $session->getName());
  15. }