- Context
- 操作数据
- 方法列表
- registerItemHandler
- 实现原理
Context
ContextManager上下文管理器
在swoole中,由于多个协程是并发执行的,因此不能使用类静态变量/全局变量保存协程上下文内容。使用局部变量是安全的,因为局部变量的值会自动保存在协程栈中,其他协程访问不到协程的局部变量。
操作数据
在 EasySwooleEvent.php 的onRequest 中 set数据:
<?phppublic static function onRequest(Request $request, Response $response): bool{ContextManager::getInstance()->set('requestData',$request->getRequestParam());// TODO: Implement onRequest() method.return true;}
App\Controller\Index.php可直接调用:
<?php/*** Created by PhpStorm.* User: Tioncico* Date: 2019/3/8 0008* Time: 15:16*/namespace App\HttpController;use App\Utility\Excel;use EasySwoole\Component\Context\ContextManager;use EasySwoole\Http\AbstractInterface\Controller;use EasySwoole\Utility\Random;use EasySwoole\VerifyCode\Conf;use EasySwoole\VerifyCode\VerifyCode;class Index extends Controller{function index(){$data = ContextManager::getInstance()->get('requestData');$this->response()->write(json_encode($data));}}
同理,在任意地方set的数据,都是处于当前协程的共享数据,和php-fpm中的超全局变量性质类似,可通过该组件进行实现$_GET,$_SESSION,$_POST等超全局变量的任意位置获取,修改等功能
方法列表
<?phppublic function set($key,$value,$cid = null){};//设置一个变量,cid为null时为当前协程public function get($key,$cid = null){};//获取一个变量,cid为null时为当前协程public function unset($key,$cid = null){};//删除一个变量,cid为null时为当前协程public function destroy($cid = null){};//销毁协程数据,cid为null时为当前协程public function getCid($cid = null):int{};//默认为获取当前协程id,并实现了协程关闭后,自动销毁该协程数据public function destroyAll($force = false){};//销毁所有协程数据public function getContextArray($cid = null){};//获取当前协程数据列表,cid为null时为当前协程public function registerItemHandler($key, ContextItemHandlerInterface $handler):ContextManager();//注册自定义存储,销毁逻辑
registerItemHandler
ContextManager提供了另一种设置方式,registerItemHandler方法去注册需要额外处理的数据.
首先先继承EasySwoole\Component\Context\ContextItemHandlerInterface接口:
<?php/*** Created by PhpStorm.* User: Tioncico* Date: 2019/3/13 0013* Time: 14:04*/namespace App\Utility\Context;use EasySwoole\Component\Context\ContextItemHandlerInterface;class RegisterClassHandel implements ContextItemHandlerInterface{protected $className;public function __construct($className){$this->className = $className;}/*** 当ContextManager get 时,会调用该方法* 可以使用该方法进行 get 的初始化操作* 例如set mysql时,可以在这里获取连接池* 例如set 某个对象时,可以在这里初始化对象属性,等* onContextCreate* @author Tioncico* Time: 14:09*/function onContextCreate(){$class = new $this->className;$class->context = '测试内容';return $class;// TODO: Implement onContextCreate() method.}/*** 当ContextManager unset或销毁时,会调用该方法* 可以使用该方法进行销毁后的操作* 例如set mysql 需要销毁时,可以在这里回收连接池* 例如set 某个对象时,可以在这里清除对象属性,等* onDestroy* @param $context* @author Tioncico* Time: 14:11*/function onDestroy($context){unset($context);return true;// TODO: Implement onDestroy() method.}}
注册 stdClass
<?phppublic static function onRequest(Request $request, Response $response): bool{ContextManager::getInstance()->registerItemHandler('stdclass',new RegisterClassHandel(\stdClass::class));// TODO: Implement onRequest() method.return true;}
注册之后,其实并没有new stdClass,只有get的时候才有new.在控制器调用:
<?php/*** Created by PhpStorm.* User: Tioncico* Date: 2019/3/8 0008* Time: 15:16*/namespace App\HttpController;use App\Utility\Excel;use EasySwoole\Component\Context\ContextManager;use EasySwoole\Http\AbstractInterface\Controller;use EasySwoole\Utility\Random;use EasySwoole\VerifyCode\Conf;use EasySwoole\VerifyCode\VerifyCode;class Index extends Controller{function index(){$data = ContextManager::getInstance()->get('stdclass');var_dump($data);$this->response()->write(json_encode($data));}}
控制台输出:
object(stdClass)#52 (1) {["context"]=>string(12) "测试内容"}
实现原理
context上下文管理器,是通过协程id作为key,进程单例模式,实现的,确保每个协程操作的都是当前协程数据,并通过defer,实现了协程结束后自动销毁,用户无需进行任何的回收处理,只管用就行
