手动配置Swoole完美支持ThinkPHP5.1开发之排坑指南之路由篇

前言

本文主要讲的是怎么在thinkPHP中配置swoole代码使其与thinkPHP协同工作。此法配置亦可应用于其他框架,但是坑不知道还是不是那个坑了,本文不予讨论。

swoole版本是目前最新版4.5.0,thinkPHP的版本是5.1的,centos7+nginx1.16.1+php7.4

swoole扩展安装方法:https://blog.csdn.net/Alen_xiaoxin/article/details/105048154

正文

1、下载thinkPHP:http://www.thinkphp.cn/donate/download/id/1041.html

2、解压之后放到网站根目录,添加server目录,并在其中创建http_server.php文件,如下所示:

//http_server.php
<?php
/**
 * Created by 20.
 * User: 20
 * Date: 2020/4/8
 * Time: 下午 13:09:11
 */
$http = new Swoole\Http\Server("0.0.0.0", 9501);

$http->set([
    'document_root' => '/yourpath/public/static', // swoolev4.4.0以下版本, 此处必须为绝对路径,项目目录,也就是存放静态文件的地方,此篇文章不会用到这个
    'enable_static_handler' => true,
    'worker_num' => 5,
]);

$http->on('WorkerStart', function(Swoole\Server $server, int $workerId){
    // 定义应用目录
    define('APP_PATH', __DIR__ . '/../application/'); //来自public/index
    // 加载基础文件
    require __DIR__ . '/../thinkphp/base.php'; //来自thinkphp/start.php

});

$http->on('request', function ($request, $response) {

    //赋值框架所需的各个全局变量
    if (isset($request->server)) {
        foreach ($request->server as $k => $v) {
            $_SERVER[strtoupper($k)] = $v;
        }
    }

    if (isset($request->header)) {
        foreach ($request->header as $k => $v) {
            $_SERVER[strtoupper($k)] = $v;
        }
    }
    if (isset($request->get)) {
        foreach ($request->get as $k => $v) {
            $_GET[$k] = $v;
        }
    }
    if (isset($request->post)) {
        foreach ($request->post as $k => $v) {
            $_POST[$k] = $v;
        }
    }
    //todo cookie

    ob_start();
    // 执行应用并响应
    try {
        think\Container::get('app', [defined('APP_PATH') ? APP_PATH : ''])
            ->run()
            ->send();
    } catch (\Exception $e) {
        //todo
    }
    $res = ob_get_contents();
    ob_end_clean();
    $response->end($res);
});

$http->start();

3、调试路由

记得每次改完代码重启一下http_server,否则代码不生效。

按照上边代码方式写完之后,可以在在终端进到server目录直接执行

php http_server.php

来启动server。

通过浏览器访问以下三个url都可直接访问到application/index/controller/index.php文件的index方法:

http://example.com:9501/index/index/index

http://example.com:9501/?s=index/index/index

http://example.com:9501

index.php文件下还有一个hello方法:

当用上边类似url访问时:

http://example.com:9501/index/index/hello

http://example.com:9501/?s=index/index/hello

会一直显示index方法的输出内容。使用tp的方法打印出当前请求的方法时,显示的都是index方法:

echo '--action--'.request()->action();

原因:

从入口函数run开始查找:

run方法在thinkphp/library/think/App.php文件中,其方法中有一行是进行url路由检测,如下所示:

$this->request->path();这段代码指向的是thinkphp/library/think/Request.php文件中的path()方法:

该方法中if判断就是swoole调用过程中总是请求index方法的凶手之一,每次判断path是否为null,解决方法有两种:

  1. 直接将if的条件和结尾注释掉,只保留里边的执行代码。
  2. 在http_server.php文件的中添加close方法,每次执行完一个worker关闭客户端连接:

建议使用第一种方法解决。

上边两种方法搞定之后,还有一个坑就是path方法执行代码里边有一个pathinfo的方法,获取URL请求的PATH_INFO的:

进入此方法首先就是注释掉最外层的if判断,说实话,这俩方法的if判断也节省不了什么时间,而且这时候还出了bug可不得给干掉。

我们在通过兼容模式http://example.com:9501/?s=index/index/hello请求的时候这个时候任何方法都是正常的,但是如果使用http://example.com:9501/index/index/hello这个方式请求的时候就一直会是index方法的返回了,经调试,发现,使用swoole的http_server进行访问的时候默认是cli模式

在上边cli判断的代码中,浏览器访问是得不到正确的PATH_INFO的,始终会被上边代码赋值为空字符串。

修改下上边代码改为下边代码即可:

$_SERVER['PATH_INFO'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : $_SERVER['REQUEST_URI'];

修改后如下:

重启httpserver再次使用各种姿势通过浏览器访问框架内各个方法发现畅通无阻。

总结

后边不知道还有什么坑。

发布了121 篇原创文章 · 获赞 102 · 访问量 38万+

猜你喜欢

转载自blog.csdn.net/Alen_xiaoxin/article/details/105394415
今日推荐