这样修改源码来获取当前Webman当前执行的路由是否可行?

LEO_D86

这个方法有问题,最新的修改方法在评论中。

没啥时间通读代码了,直接在Webman\app类的findRoute方法中将找到的路由直接赋值到请求对象上,然后可以在其他地方通过请求对象来访问当前路由。就是不知道有没有啥副作用,有大佬能看看不?

第一步 修改类Webman\Http\Request,添加一个新的公共属性currentRoute来存储在应用中找到的路由对象。

第二部 修改类Webman\app

// 修改 Webman\app
 protected static function findRoute($connection, $path, $key, Request $request)
 {
    $ret = Route::dispatch($request->method(), $path);
    if ($ret[0] === Dispatcher::FOUND) {
        $ret[0] = 'route';
        $callback = $ret[1]['callback'];
        $route = $request->currentRoute = $ret[1]['route']; // 将找到的路由赋值到当前请求对象上
        $app = $controller = $action = '';
        $args = !empty($ret[2]) ? $ret[2] : null;
        if (\is_array($callback) && isset($callback[0]) && $controller = \get_class($callback[0])) {
            $app = static::getAppByController($controller);
            $action = static::getRealMethod($controller, $callback[1]) ?? '';
        }
        $callback = static::getCallback($app, $callback, $args, true, $route);
        static::$_callbacks[$key] = [$callback, $app, $controller ? $controller : '', $action];
        list($callback, $request->app, $request->controller, $request->action) = static::$_callbacks[$key];
        static::send($connection, $callback($request), $request);
        if (\count(static::$_callbacks) > 1024) {
            static::clearCache();
        }
        return true;
    }
     return false;
}
1274 3 0
3个回答

walkor

可行

  • LEO_D86 2022-03-15

    其实不太行,应用在找到路由以后会缓存路由信息到 static::$_callbacks 中,所以在第二次访问的时候会出现问题。目前找到了其他办法,暂时可以用,我稍后改一下内容。

LEO_D86

上面的修改方案有问题,下面是新的修改方式。

修改类\Webman\App,如下

protected static function findRoute($connection, $path, $key, Request $request)
{
    $ret = Route::dispatch($request->method(), $path);

    if ($ret[0] === Dispatcher::FOUND) {
        $ret[0] = 'route';
        $callback = $ret[1]['callback'];
        $route = $ret[1]['route'];
        $app = $controller = $action = '';
        $args = !empty($ret[2]) ? $ret[2] : null;

        if (\is_array($callback) && isset($callback[0]) && $controller = \get_class($callback[0])) {
            $app = static::getAppByController($controller);
            $action = static::getRealMethod($controller, $callback[1]) ?? '';
        }

        $callback = static::getCallback($app, $callback, $args, true, $route);
        static::$_callbacks[$key] = [$callback, $app, $controller ? $controller : '', $action, $route]; // 将找到的路由对象缓存起来
        list($callback, $request->app, $request->controller, $request->action, $request->currentRoute) = static::$_callbacks[$key]; // 将路由对象复制到请求对象中
        static::send($connection, $callback($request), $request);

        if (\count(static::$_callbacks) > 1024) {
            static::clearCache();
        }

        return true;
    }
    return false;
}

public function onMessage(TcpConnection $connection, $request)
{
    try {
        static::$_request = $request;
        static::$_connection = $connection;
        $path = $request->path();
        $key = $request->method() . $path;

        if (isset(static::$_callbacks[$key])) {
            list($callback, $request->app, $request->controller, $request->action, $request->currentRoute) = static::$_callbacks[$key]; // 从缓存的数据读取相关信息并设置请求对象属性
            static::send($connection, $callback($request), $request);
            return null;
        }

        if (static::findFile($connection, $path, $key, $request)) {
            return null;
        }

        if (static::findRoute($connection, $path, $key, $request)) {
            return null;
        }

        $controller_and_action = static::parseControllerAction($path);

        if (!$controller_and_action || Route::hasDisableDefaultRoute()) {
            $callback = static::getFallback();
            $request->app = $request->controller = $request->action = '';
            static::send($connection, $callback($request), $request);
            return null;
        }

        $app = $controller_and_action['app'];
        $controller = $controller_and_action['controller'];
        $action = $controller_and_action['action'];
        $callback = static::getCallback($app, [$controller_and_action['instance'], $action]);
        static::$_callbacks[$key] = [$callback, $app, $controller, $action];
        list($callback, $request->app, $request->controller, $request->action) = static::$_callbacks[$key];
        static::send($connection, $callback($request), $request);
    } catch (\Throwable $e) {
        static::send($connection, static::exceptionResponse($e, $request), $request);
    }

    return null;
}

修改类\Webman\Http\Request,添加一个新的公共属性currentRoute来存储在应用中找到的路由对象,然后就可以使用$request->currentRoute来访问当前路由。

需要注意的是,webman在判断路由是否执行上面似乎并没有具体区分请求方法method,导致使用不同方法访问一个路由时,依旧会执行下去,在某些时候会报错,不过目前满足了自己的开发需要。

  • 暂无评论
walkor

参照你的方案,已经支持通过 $request->route 获取路由信息,请更新。
composer require workerman/webman-framework ^1.3.2

年代过于久远,无法发表回答
🔝