文档地址:Hyperf
结合之前文章,路由和获取请求不再说明。
一、避免携程间数据混淆
根据文档:
Hyperf 内绝大部分的对象包括 Controller
都是以 单例(Singleton)
形式存在。
编写代码时请务必注意 不要 将单个请求相关的数据储存在类属性内,包括非静态属性。
实际使用的类仅仅是一个代理类,实际调用的都是从 协程上下文(Context)
中获取。
若必须存储,使用Hyperf\HttpServer\Contract\RequestInterface
对应的 Hyperf\HttpServer\Request
和yperf\HttpServer\Contract\ResponseInterface
对应的 Hyperf\HttpServer\Response。
官网说的这点比较模糊。
1.1 单例模式
单例模式定义:提供访问唯一对象的办法,可直接访问不用实例化。
class Use{
private static $object = NULL;//初始化为NULL,没有对象
private function __construct()
{
//构造函数
}
public static function getInstance()
{
//判断类内部的静态属性是否存在对象
if(!(self::$object instanceof self)){ //当前保存的内容不是当前类的对象
self::$object = new self();
}
//返回对象给外部
return self::$object;
}
}
$s1=Use::getSingleton();
我查代码,比如Hyperf\HttpServer\Contract\RequestInterface也不是单例类。
源码控制器里面继承的AbstractController为抽象类,但是php8之前对继承规范校验也不严格,所以意义不大。
declare (strict_types = 1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace App\Controller;
class IndexController extends AbstractController
{
public function index()
{
$user = $this->request->input('user', 'Hyperf');
$method = $this->request->getMethod();
return [
'method' => $method,
'message' => "Hello {$user}.",
];
}
public function test()
{
$test = $this->request->post();
var_dump($test);
}
}
#App\Controller\AbstractController
abstract class AbstractController
{
/**
* @Inject
* @var ContainerInterface
*/
protected $container;
/**
* @Inject
* @var RequestInterface
*/
protected $request;
/**
* @Inject
* @var ResponseInterface
*/
protected $response;
}
其他地方确实有静态类,但不一定像文档上说的这么多,所以设置类内变量做存储的影响还需要测试。
1.2 类内数据存储
declare (strict_types = 1);
namespace App\Controller;
use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\HttpServer\Contract\RequestInterface;
/**
* @AutoController()
*/
class TestController extends AbstractController
{
private $name;
public function index1(RequestInterface $request)
{
$user = $request->input('user', 'Hyperf');
$name = "name" . $user;
$this->request->name = $name;
$method = $this->request->getMethod();
$this->getname();
return [
'method' => $method,
'message' => "Hello {$name}.",
];
}
private function getname()
{
var_dump($this->name); //打印null
var_dump($this->request->name);//nameHyperf
}
}
证明类内数据存储使用$this->request或者$this->response。
其他类存储数据可以用以下代码存到上下文里。
public function __set($name, $value){
return Context::set(__CLASS__ . ":" .$name, $value);
}
public function __get($name){
return Context::get(__CLASS__ . ":" . $name);
}
根据文章:
hyperf 协程数据混淆的思考和分析_hyper 解决 协成上下文数据共享问题_子非 。的博客-CSDN博客
混淆大概指类内成员值第一次请求正常,第二次请求修改,第三次请求获取为修改后的值。
用php-fpm肯定不会这样,因为每次请求是开一个线程。swoole是都在单个线程共享内存,一个客户端请求应该是在一个线程里,所以多次请求后,同一个客户端请求同一个值会有不同。