Context

ContextManager上下文管理器
在swoole中,由于多个协程是并发执行的,因此不能使用类静态变量/全局变量保存协程上下文内容。使用局部变量是安全的,因为局部变量的值会自动保存在协程栈中,其他协程访问不到协程的局部变量。

操作数据

EasySwooleEvent.phponRequest 中 set数据:

  1. <?php
  2. public static function onRequest(Request $request, Response $response): bool
  3. {
  4. ContextManager::getInstance()->set('requestData',$request->getRequestParam());
  5. // TODO: Implement onRequest() method.
  6. return true;
  7. }

App\Controller\Index.php可直接调用:

  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: Tioncico
  5. * Date: 2019/3/8 0008
  6. * Time: 15:16
  7. */
  8. namespace App\HttpController;
  9. use App\Utility\Excel;
  10. use EasySwoole\Component\Context\ContextManager;
  11. use EasySwoole\Http\AbstractInterface\Controller;
  12. use EasySwoole\Utility\Random;
  13. use EasySwoole\VerifyCode\Conf;
  14. use EasySwoole\VerifyCode\VerifyCode;
  15. class Index extends Controller
  16. {
  17. function index()
  18. {
  19. $data = ContextManager::getInstance()->get('requestData');
  20. $this->response()->write(json_encode($data));
  21. }
  22. }

同理,在任意地方set的数据,都是处于当前协程的共享数据,和php-fpm中的超全局变量性质类似,可通过该组件进行实现$_GET,$_SESSION,$_POST等超全局变量的任意位置获取,修改等功能

方法列表

  1. <?php
  2. public function set($key,$value,$cid = null){};//设置一个变量,cid为null时为当前协程
  3. public function get($key,$cid = null){};//获取一个变量,cid为null时为当前协程
  4. public function unset($key,$cid = null){};//删除一个变量,cid为null时为当前协程
  5. public function destroy($cid = null){};//销毁协程数据,cid为null时为当前协程
  6. public function getCid($cid = null):int{};//默认为获取当前协程id,并实现了协程关闭后,自动销毁该协程数据
  7. public function destroyAll($force = false){};//销毁所有协程数据
  8. public function getContextArray($cid = null){};//获取当前协程数据列表,cid为null时为当前协程
  9. public function registerItemHandler($key, ContextItemHandlerInterface $handler):ContextManager();//注册自定义存储,销毁逻辑

registerItemHandler

ContextManager提供了另一种设置方式,registerItemHandler方法去注册需要额外处理的数据.
首先先继承EasySwoole\Component\Context\ContextItemHandlerInterface接口:

  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: Tioncico
  5. * Date: 2019/3/13 0013
  6. * Time: 14:04
  7. */
  8. namespace App\Utility\Context;
  9. use EasySwoole\Component\Context\ContextItemHandlerInterface;
  10. class RegisterClassHandel implements ContextItemHandlerInterface
  11. {
  12. protected $className;
  13. public function __construct($className)
  14. {
  15. $this->className = $className;
  16. }
  17. /**
  18. * 当ContextManager get 时,会调用该方法
  19. * 可以使用该方法进行 get 的初始化操作
  20. * 例如set mysql时,可以在这里获取连接池
  21. * 例如set 某个对象时,可以在这里初始化对象属性,等
  22. * onContextCreate
  23. * @author Tioncico
  24. * Time: 14:09
  25. */
  26. function onContextCreate()
  27. {
  28. $class = new $this->className;
  29. $class->context = '测试内容';
  30. return $class;
  31. // TODO: Implement onContextCreate() method.
  32. }
  33. /**
  34. * 当ContextManager unset或销毁时,会调用该方法
  35. * 可以使用该方法进行销毁后的操作
  36. * 例如set mysql 需要销毁时,可以在这里回收连接池
  37. * 例如set 某个对象时,可以在这里清除对象属性,等
  38. * onDestroy
  39. * @param $context
  40. * @author Tioncico
  41. * Time: 14:11
  42. */
  43. function onDestroy($context)
  44. {
  45. unset($context);
  46. return true;
  47. // TODO: Implement onDestroy() method.
  48. }
  49. }

注册 stdClass

  1. <?php
  2. public static function onRequest(Request $request, Response $response): bool
  3. {
  4. ContextManager::getInstance()->registerItemHandler('stdclass',new RegisterClassHandel(\stdClass::class));
  5. // TODO: Implement onRequest() method.
  6. return true;
  7. }

注册之后,其实并没有new stdClass,只有get的时候才有new.在控制器调用:

  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: Tioncico
  5. * Date: 2019/3/8 0008
  6. * Time: 15:16
  7. */
  8. namespace App\HttpController;
  9. use App\Utility\Excel;
  10. use EasySwoole\Component\Context\ContextManager;
  11. use EasySwoole\Http\AbstractInterface\Controller;
  12. use EasySwoole\Utility\Random;
  13. use EasySwoole\VerifyCode\Conf;
  14. use EasySwoole\VerifyCode\VerifyCode;
  15. class Index extends Controller
  16. {
  17. function index()
  18. {
  19. $data = ContextManager::getInstance()->get('stdclass');
  20. var_dump($data);
  21. $this->response()->write(json_encode($data));
  22. }
  23. }

控制台输出:

  1. object(stdClass)#52 (1) {
  2. ["context"]=>
  3. string(12) "测试内容"
  4. }

实现原理

context上下文管理器,是通过协程id作为key,进程单例模式,实现的,确保每个协程操作的都是当前协程数据,并通过defer,实现了协程结束后自动销毁,用户无需进行任何的回收处理,只管用就行