使用Composer从零开发一个简单的restful框架(05)-路由分组

路由分组

新建core/Route.php,内容如下

<?php
namespace core;


class Route {
    private string $group; //分组
    private array $routes = []; //分组下的路由, 包括分组


    public function __construct(string $group) {
        $this->group = $group;
    }


    public function getGroup(): string {
        return $this->group;
    }

    public function getRoutes(): array {
        return $this->routes;
    }

    public function addRoute(string $method, string $uri, \Closure | string $cb): void {
        $method = strtoupper($method);
        slash_add($uri);

        $item = new RouteItem($method, $uri, $cb);

        $this->routes[] = $item;
    }

    public function addChild(Route $child): void {
        $this->routes[] = $child;
    }
}

编辑core/Router.php,内容如下

<?php
namespace core;


class Router {
    private Route $curr; //当前路由(路由分组开始时会切换, 分组代码执行完后再切换回来)


    public function __construct() {
        // 根路由
        $this->curr = new Route('/');

        // 加载路由文件(路由文件使用 $router 访问)
        $router = $this;

        foreach (glob(PATH_ROUTE . '*.php') as $routeFile) {
            require_once $routeFile;
        }
    }


    // 开始路由处理
    public function routing(Request $request, Response $response): void {
        $uri = $request->getUri();
        slash_add_end($uri);

        $this->dispatch($this->curr, $request->getMethod(), $uri, $request, $response);

        $response->send();
    }


    // 路由分组
    public function group(string $group, \Closure $cb): void {
        $lastRoute = $this->curr;

        slash_add_head($group);
        $route = new Route($group);

        $this->curr->addChild($route);
        $this->curr = $route;

        call_user_func($cb, $this);

        $this->curr = $lastRoute;
    }


    public function get(string $uri, \Closure | string $cb): void {
        $this->curr->addRoute('get', $uri, $cb);
    }

    public function post(string $uri, \Closure | string $cb): void {
        $this->curr->addRoute('post', $uri, $cb);
    }

    public function put(string $uri, \Closure | string $cb): void {
        $this->curr->addRoute('put', $uri, $cb);
    }

    public function delete(string $uri, \Closure | string $cb): void {
        $this->curr->addRoute('delete', $uri, $cb);
    }

    public function patch(string $uri, \Closure | string $cb): void {
        $this->curr->addRoute('patch', $uri, $cb);
    }

    public function options(string $uri, \Closure | string $cb): void {
        $this->curr->addRoute('options', $uri, $cb);
    }

    public function any(string $uri, \Closure | string $cb): void {
        $methods = ['get', 'post', 'put', 'delete', 'patch', 'options'];
        foreach ($methods as $method) {
            $this->curr->addRoute($method, $uri, $cb);
        }
    }


    private function dispatch(Route $route, string $method, string $uri, Request $request, Response $response): void {
        $group = $route->getGroup();

        // 分组不会有命名参数, 不包含直接返回
        if (!str_contains($uri, $group)) return;

        $uri = substr($uri, strlen($group));
        slash_add_head($uri);

        $routes = $route->getRoutes();

        foreach ($routes as $item) {
            if ($item instanceof RouteItem) {
                if ($method == $item->method && $uri == $item->uri) {
                    ($item->cb)($request, $response);

                    return;
                }
            } else {
                $this->dispatch($item, $method, $uri, $request, $response);
            }
        }
    }
}

编辑route/test.php,内容如下

<?php
use core\Request;
use core\Response;
use core\Router;


/** @var Router $router */

$router->get('/', function(Request $request, Response $response) {
    $response->text('from /');
});

$router->get('/test', function(Request $request, Response $response) {
    $response->text('from /test');
});

$router->get('/test2', function(Request $request, Response $response) {
    $response->text('from /test2');
});


$router->group('group', function(Router $router) {
    $router->get('', function(Request $request, Response $response) {
        $response->text('from /group');
    });

    $router->get('test', function(Request $request, Response $response) {
        $response->text('from /group/test');
    });
});

测试

浏览器访问路由对应链接

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!