TP5集成Swoole

环境准备

thinkphp5.1和swoole

tp5的安装使用composer安装,使用以下命令安装

1
composer create-project topthink/think  tp5  --prefer-dist

thinkphp5.1.18更新,完善了swoole的支持,不用再自己更改Request类了


ThinkPHP5.1.18版本发布——完善Swoole/Workerman支持

swoole的安装参考我写的swoole安装教程

swoole简单使用

一般来说我们的浏览器发起一个请求先走nginx或apache,然后通过fast_CGI交给php来执行php代码,FPM是fast_cgi的进程管理器,FPM通过一些配置管理很多的fast_cgi进程。
当我们使用swoole来开启一个http服务的话就不需要使用fpm了。

首先看官方文档的一个例子

1
2
3
4
5
6
7
$http = new swoole_http_server("127.0.0.1", 9501);
//在收到一个http请求后,会调用该函数
$http->on('request', function ($request, $response) {
//发送http响应体,结束请求处理
$response->end("<h1>Hello Swoole. #".rand(1000, 9999)."</h1>");
});
$http->start();

如果想加载静态的html文件,可以使用document_root配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$http = new swoole_http_server("127.0.0.1", 9501);
//worker_num设置启动的worker进程数
$http->set(
[
'enable_static_handler' => true,
'document_root' => "/thinkphp/public/static/live",
'worker_num' => 5,
]
);

$http->on('request', function ($request, $response) {
$response->end("<h1>Hello Swoole. #".rand(1000, 9999)."</h1>");
});
$http->start();

使用命令行运行该程序,打开浏览器即可看到结果,这里就不给结果了。

tp5结合swoole

首先把上面的http_server的代码放到tp5的项目目录下,我是放到了项目的根目录下

  • 如果我们不修改,当我们输入url的时候并不会找到相应的控制器方法。swoole通过request事件,通过回调函数处理相应的请求get,post等。

  • 通过swoole的workerstart事件回调函数加载框架代码

  • 通过观察tp5的代码可以看到,index.php首先加载了引导文件start.php, start.php又加载了base.php文件。我们要加载的便是该文件

1
2
3
4
5
6
7

$http->on('WorkerStart',function(swoole_server $server,$worker_id){
define('APP_PATH', __DIR__ . '/../application/');
// 这里 引入 base.php 而不引入start.php 是因为
// start.php 的话 就会执行thinkphp 的相应的控制器方法了
require __DIR__ . '/../thinkphp/base.php';
});

这样便把tp5的代码加载到worker进程里,接着处理请求部分
因为tp5使用原生的php代码,所以需要把swoole的请求转换下。swoole接收get,post跟原生的不一样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
$http->on('request', function ($request, $response) use($http){
if(isset($request->server)){
foreach($request->server as $k => $v){
$_SERVER[strtoupper($k)] = $v;
}
}

if(isset($request->server)){
foreach($request->server as $k => $v){
$_SERVER[strtoupper($k)] = $v;
}
}
//swoole对于超全局数组并不会释放,所以要先清空一次
$_GET = [];
if(isset($request->get)){
foreach ($request->get as $k => $v){
$_GET[$k] = $v;
}
}

$_POST = [];
if(isset($request->post)){
foreach ($request->post as $k => $v){
$_POST[$k] = $v;
}
}
//把返回放到一个缓冲区里
ob_start();
try {
think\Container::get('app', [defined('APP_PATH') ? APP_PATH : ''])
->run()
->send();
}catch(\Exception $e){

}
echo request()->action();
$res = ob_get_contents();
ob_end_clean();
$response->end($res);

});

这样改完后我们测试下

我们发现当我们修改方法时,始终显示的是index方法,这里有一个解决办法。

找到thinkphp/library/think/Request.php文件,里面有2个方法更改如下


之后我们就可以正常的通过url进行访问了。这里改成这样的原因,是因为tp会把模块,控制器,方法放到一个变量中,如果我们有重复访问同一个控制器,方法时这样比较高效。但worker进程并不会注销变量。就造成了访问不同控制器,方法始终是同一个控制器,方法。

感谢土豪
0%