• Context
    • 操作数据
    • 方法列表
      • registerItemHandler
    • 实现原理

    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,实现了协程结束后自动销毁,用户无需进行任何的回收处理,只管用就行