当前位置: 首页 > ai >正文

Swoole-添加自定义路由实现控制器访问

swoole本身不支持路由功能,默认情况我们实现路由访问可能要这样

        $path = $request->server['request_uri']switch ($path){case '/favicon.ico':$response->status(404);$response->end('Not Found');break;case '/abc/def/gg':$response->end("/abc/def/gg");break;default://var_dump($path);$response->end('<h1>Swoole HTTP Server YYDS.</h1>');break;}

时间一长满屏都是这里的路由判断。

为了防止改方案时近视度数蹭蹭涨。。。。。。

我们需要添加添加一个自定义路由。

作为资深代码搬运工,我们老规矩,先从官方文档复制一个httpServer demo放到index.php文件中

//index.php
$http = new Swoole\Http\Server('0.0.0.0', 9501);$http->on('Request', function ($request, $response) {$response->header('Content-Type', 'text/html; charset=utf-8');$response->end('<h1>Hello Swoole. #' . rand(1000, 9999) . '</h1>');
});$http->start();

启动不用我说了,不成功直接关电脑。

因为swoole的重启命令无法重启被加载过的文件,所以这里做一个自动重启的bash,简单粗暴的重启服务

#!/bin/bashDIR_TO_WATCH="."declare -A LAST_MODIFIED
while IFS= read -r file; doLAST_MODIFIED["$file"]=$(stat -c %Y "$file")
done < <(find "$DIR_TO_WATCH" -type f)start_swoole() {php "$DIR_TO_WATCH/index.php" &PID=$!echo "Swoole server started with PID: $PID"
}stop_swoole() {if [ -n "$PID" ]; thenecho "Stopping Swoole server (PID: $PID)..."kill -TERM "$PID"wait "$PID"echo "Swoole server stopped (PID: $PID)"fi
}trap stop_swoole EXIT# swoole
start_swoolewhile true; do# 检查是否有文件被修改MODIFIED=falsewhile IFS= read -r file; doCURRENT_MODIFIED=$(stat -c %Y "$file")if [ "${LAST_MODIFIED["$file"]}" != "$CURRENT_MODIFIED" ]; thenMODIFIED=trueLAST_MODIFIED["$file"]="$CURRENT_MODIFIED"fidone < <(find "$DIR_TO_WATCH" -type f)# 如果有文件被修改,重启 Swoole 服务器if [ "$MODIFIED" = true ]; thenecho "$DIR_TO_WATCH 被修改,服务重启。。。"stop_swoolestart_swoolefisleep 1
done

启动这个bash

现在开始进入正题

首先创建一个Routes的class

然后创建一个存放路由的变量,并引入swoole相关的文件

然后添加一个方法对routes做简单处理

<?phpuse Swoole\Http\Request;
use Swoole\Http\Response;
class Routes
{protected $routes = [];//addRoute对routes做简单处理public function addRoute($method, $uri,callable $action){$this->routes[] = ['method'  => strtoupper($method),'pattern' => '/^' . str_replace('/', '\/', $uri) . '$/', //地址替换为正则'handler' => $action];var_dump($this->routes);}}

接下来我们继续在路由类中创建一个分发路由的函数,

解析请求路径和请求方法,再加一个404的页面处理

// 路由分发方法
public function dispatch(Request $request, Response $response): void
{$requestMethod = strtoupper($request->server['request_method'] ?? 'GET');$requestPath = parse_url($request->server['request_uri'] ?? '/', PHP_URL_PATH);/** 此处先留白 **/$response->status(404);$response->end('404 Not Found');}

接下来修改index.php

随便添加两个路由地址,并返回随便什么内容

//index.php
require_once 'Routes.php';
$http = new Swoole\Http\Server('0.0.0.0', 9501);$routes = new Routes();
$routes->addRoute('get', '/',function ($request, $response) {$response->end('<h1>Home. #' . rand(1000, 9999) . '</h1>');
});
$routes->addRoute('get', '/abc/aa',function ($request, $response) {$response->end('<h1>Hello AA. #' . rand(1000, 9999) . '</h1>');
});
$routes->addRoute('get', '/abc/bb',function ($request, $response) {$response->end('<h1>Hello BB. #' . rand(1000, 9999) . '</h1>');
});
$http->on('Request', function ($request, $response)use($routes) {$response->header('Content-Type', 'text/html; charset=utf-8');//注释send//$response->end('<h1>Hello Swoole ++++  asdsf. #' . rand(1000, 9999) . '</h1>');//分发路由$routes->dispatch($request, $response);
});$http->start();

这时候打开浏览器,页面会显示你自己写的404 not fund

but 哈 别急。

路由分发方法主要解析routes数组,并执行routes中的回调函数

所以接下来在上面留白地方遍历routes,

    // 路由分发public function dispatch(Request $request, Response $response): void{$requestMethod = strtoupper($request->server['request_method'] ?? 'GET');$requestPath = parse_url($request->server['request_uri'] ?? '/', PHP_URL_PATH);//遍历routesforeach ($this->routes as $route) {if ($route['method'] !== $requestMethod) {continue;}if (preg_match($route['pattern'], $requestPath, $matches)) {// 提取动态参数$params = [];foreach ($matches as $key => $value) {if (is_string($key)) {$params[$key] = $value;}}$route['handler']($request, $response, ...array_values($params));return;  // 路由匹配成功就别继续了}}// 404 处理$response->status(404);$response->end('404 Not Found');}

现在等待swoole重启后刷新页面、主页应该显示Home # xxx

继续访问你定义的几个路由地址,页面返回你预期的内容

实际应用过程中,我们定义了路由应该是get(),post(),put()这样的方法

路由定义也不要在index.php

所以接下来我们继续修改Router文件,修改addRoute的可见性和实现方法,支持控制器文件,并添加对应请求方法

修改后的index.php代码

//index.php
require_once 'Routes.php';
require_once 'IndexController.php';
require_once 'route.php';
$http = new Swoole\Http\Server('0.0.0.0', 9501);
/** @var Routes $routes */
$http->on('Request', function ($request, $response)use($routes) {$response->header('Content-Type', 'text/html; charset=utf-8');//注释send//$response->end('<h1>Hello Swoole ++++  asdsf. #' . rand(1000, 9999) . '</h1>');//分发路由$routes->dispatch($request, $response);
});$http->start();

 创建路由定义 文件route.php

<?php
//route.php
$routes = new Routes();
$routes->get('/',[IndexController::class,'index']); //添加一个控制器访问$routes->get( '/abc/aa',function ($request, $response) {$response->end('<h1>Hello AA. #' . rand(1000, 9999) . '</h1>');
});
$routes->get( '/abc/bb',function ($request, $response) {$response->end('<h1>Hello BB. #' . rand(1000, 9999) . '</h1>');
});
$routes->get( '/abc/cc',function ($request, $response) {$response->end('<h1>Hello cc. #' . rand(1000, 9999) . '</h1>');
});

 修改Routes文件

//Routes
use Swoole\Http\Request;
use Swoole\Http\Response;
class Routes
{protected $routes = [];public static $verbs = ['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'];public function get($uri,$action){$this->addRoute('get', $uri, $action);}public function post($uri,$action){$this->addRoute('post', $uri, $action);}public function put($uri,$action){$this->addRoute('put', $uri, $action);}public function delete($uri, $action){$this->addRoute('delete', $uri, $action);}public function any($uri, $action){foreach(self::$verbs as $verb){$this->addRoute($verb, $uri, $action);}}//修改可见性protected function addRoute($method, $uri, $action){// 将路径中的 {param} 转换为正则表达式$pattern = preg_replace_callback('/\{(\w+)\}/', function ($matches) {return '(?P<'.$matches[1].'>\w+)';}, $uri);if(is_array($action)) //添加对控制器支持{$action = function (Request $request,Response $response, ...$params)use($action){[$class, $method] = $action;$controller = new $class;return $controller->$method($request, $response, ...$params);};}$this->routes[] = ['method'  => strtoupper($method),'pattern' => '/^' . str_replace('/', '\/', $pattern) . '$/','handler' => $action];}// 路由分发public function dispatch(Request $request, Response $response): void{$requestMethod = strtoupper($request->server['request_method'] ?? 'GET');$requestPath = parse_url($request->server['request_uri'] ?? '/', PHP_URL_PATH);foreach ($this->routes as $route) {if ($route['method'] !== $requestMethod) {continue;}if (preg_match($route['pattern'], $requestPath, $matches)) {// 提取动态参数$params = [];foreach ($matches as $key => $value) {if (is_string($key)) {$params[$key] = $value;}}$route['handler']($request, $response, ...array_values($params));return; // 路由匹配成功就别继续了}}// 404 处理$response->status(404);$response->end('404 Not Found');}}

添加一个控制器IndexController

<?php
use Swoole\Http\Request;
use Swoole\Http\Response;
class IndexController
{public function index(Request $request, Response $response){$response->end('<h1>INDEX Controller </h1>');}}

浏览器访问首页

显示效果和预期一致, 

至于请求参数,那是request的工作

http://www.xdnf.cn/news/1239.html

相关文章:

  • 互联网三高-高性能之IO网络技术底层机制
  • 《TCP/IP详解 卷1:协议》之第四、五章:ARP RARP
  • CLIP | 训练过程中图像特征和文本特征的在嵌入空间中的对齐(两个投影矩阵的学习)
  • 武装Burp Suite工具:RouteVulScan插件_被动扫描发现漏洞.
  • python高级特性01
  • 代码随想录算法训练营Day34
  • (16)VTK C++开发示例 --- 转换文件格式
  • ProxySQL 性能调优工具推荐
  • day48—双指针-通过删除字母匹配到字典最长单词(LeetCode-524)
  • 【随机过程】柯尔莫哥洛夫微分方程总结
  • 算力网络的早期有关论文——自用笔记
  • 在Pytorch中使用Tensorboard可视化训练过程
  • 基于DeepSeek的网络爬虫技术创新与实践应用
  • 若依如何切换 tab 不刷新
  • Google 开发者政策中心 - 3 月版
  • 【Spring】AutoConfigureOrder与Order注解的区别与使用方式
  • Gboard安卓版手势输入与多语言支持全面评测【输入顺滑】
  • Java数组
  • C++抽象基类定义与使用
  • linux kallsys
  • 探索Cangjie Magic:仓颉编程语言原生的LLM Agent开发新范式
  • mcp 客户端sse远程调用服务端与本地大模型集成实例
  • Python简介与入门
  • 多路转接select服务器
  • 数据结构:链表
  • 近几年字节测开部分面试题整理
  • 明远智睿2351开发板四核1.4G Linux处理器:驱动创新的引擎
  • Protues8.11安装只需5步骤即可。
  • 如何创建Vue3工程
  • 状态管理最佳实践:Riverpod响应式编程