关于webman1.5中使用request依赖注入问题

chineyoung

问题描述

这里详细描述问题
我在使用依赖注入的过程发现,我如果在构造方法中注入了request,会导致在使用的时候一些方法调用会有问题,比如getRemoteIp()、getRealIp()之类的

程序代码

// 注释的方式如下,
// 已经在dependence.php添加了\support\Request::class => function () {return request();}
use support\Request;
class RequestService
{
    public function __construct(public Request $req){}
    // 第一次通过接口调用这个方法的话,有值,但是如果通过接口调用的话,会报错
    public function test(){
        return dd($this->req->getRemoteIp());
    }
}

测试追加


// 其中进程数设置为1,控制器复用也默认关闭,接口请求为post,测试发现第一次会返回正常的ip,当再次调用则依旧显示报错

// 控制器
namespace app\controller;

use support\Request;

class IndexController
{

    public function __construct(public Request $req){}
    public function index(Request $request)
    {
        return json($this->req->getRemoteIp());
    }
}

// container.php

$builder = new \DI\ContainerBuilder();
$builder->addDefinitions(config('dependence', []));
$builder->useAutowiring(true);
$builder->useAnnotations(true);
return $builder->build();

// dependence.php
return [
    \support\Request::class => function () {
        return \request();
    },
];

报错信息

Error: Call to a member function getRemoteIp() on null in /work/codingItems/webman-api/vendor/workerman/webman-framework/src/Http/Request.php:178
Stack trace:
#0 /work/codingItems/webman-api/vendor/workerman/webman-framework/src/Http/Request.php(215): Webman\Http\Request->getRemoteIp()
#1 /work/codingItems/webman-api/app/common/api/request/RequestService.php(35): Webman\Http\Request->getRealIp()
#2 /work/codingItems/webman-api/app/admin/controller/PersonalController.php(18): app\common\api\request\RequestService->checkGetKeys()
#3 /work/codingItems/webman-api/vendor/workerman/webman-framework/src/App.php(325): app\admin\controller\PersonalController->login()
#4 /work/codingItems/webman-api/vendor/workerman/webman-framework/src/App.php(141): Webman\App::Webman\{closure}()
#5 /work/codingItems/webman-api/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
#6 /work/codingItems/webman-api/vendor/workerman/workerman/Events/Select.php(311): Workerman\Connection\TcpConnection->baseRead()
#7 /work/codingItems/webman-api/vendor/workerman/workerman/Worker.php(1635): Workerman\Events\Select->loop()
#8 /work/codingItems/webman-api/vendor/workerman/workerman/Worker.php(1426): Workerman\Worker::forkOneWorkerForLinux()
#9 /work/codingItems/webman-api/vendor/workerman/workerman/Worker.php(1400): Workerman\Worker::forkWorkersForLinux()
#10 /work/codingItems/webman-api/vendor/workerman/workerman/Worker.php(560): Workerman\Worker::forkWorkers()
#11 /work/codingItems/webman-api/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
#12 /work/codingItems/webman-api/start.php(4): support\App::run()
#13 {main} [] []

截图报错信息里报错文件相关代码

首次调用
再次调用

操作系统及workerman/webman等框架组件具体版本

workerman/webman-framework:v1.5.11

初始化webman项目的环境为

系统环境为wsl2中的Ubuntu20.04
php版本为8.1.7

546 1 0
1个回答

walkor

你的RequestService是怎么初始化的

  • chineyoung 2023-11-22

    通过接口,首先是去注册了\app\common\api\interfaces\RequestInterface::class => function (ContainerInterface $c) {
    return $c->make(\app\common\api\request\RequestService::class);
    },然后编写class RequestService implements RequestInterface,其中RequestService中就只和上面写的一样,只有public function __construct(public Request $req){}这一个地方初始化,最后控制器里面public function __construct(public RequestInterface $req),利用$this->req->test()

  • chineyoung 2023-11-22

    php用的是8.1,以及我发现如果把RequestService中的public function __construct(public Request $req){}删除,然后服务内的之前的依赖注入的req参数用帮助函数request(),倒是不会出现这个问题

  • walkor 2023-11-22

    看现象是RequestService示例持久化到内存了,你每次使用的都是第一次实例化的RequestService。里面的request对象是过期的,连接已经断开,connection为null,无法获取getRemoteIp

  • chineyoung 2023-11-22

    大大,针对于这种情况有什么解决方案嘛?还是说就老老实实用帮助方法就好了,不去对于Request做非控制器外的注入

  • walkor 2023-11-22

    需要看下是不是复用了RequestService实例。进程数设置为1,然后RequestService的构造函数里输出日志。
    看下是否是每次请求都初始化新的RequestService实例。
    如果RequestService实例被复用了,需要看下哪里缓存了RequestService实例,比如是否开了resue_controller复用控制器导致。

  • chineyoung 2023-11-23

    我重新初始化创建了一个webman项目,然后通过直接在初始化的IndexController示例中通过public function __construct(public Request $req){}进行依赖注入,以及在public function index(){return json($this->req->getRemoteIp());}调用,发现还是会存在第一次有值,再次调用的话就报错Call to a member function getRemoteIp() on null。但是这种情况好像只存在于post请求,get请求是正常的。其中控制器复用是默认关闭的,进程数我也设置为'count' => 1了

  • walkor 2023-11-23

    项目打包发到 walkor@workerman.net 我看下

  • chineyoung 2023-11-23

    大大,发送过去了~

🔝