欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-18 15:53:38
...

前言

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

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

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

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文件,如下所示:

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

//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方法:

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

当用上边类似url访问时:

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

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

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

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

原因:

从入口函数run开始查找:

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

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

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

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

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

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

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

  1. 直接将if的条件和结尾注释掉,只保留里边的执行代码。
  2. 在http_server.php文件的中添加close方法,每次执行完一个worker关闭客户端连接:
    手动配置Swoole完美支持ThinkPHP5.1开发之排坑指南之路由篇

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

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

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

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

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

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

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

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

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

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

修改后如下:

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

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

总结

后边不知道还有什么坑。