使用Composer从零开发一个简单的restful框架(完结)-路由中间件

最终源码

gitee.com/mirahs/phpapi

有时只需要给某个路由单独添加中间件

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

<?php
namespace core;


class RouteItem {
    public function __construct(public string $method, public string $uri, public \Closure | string $cb, public array $middleware) { }
}

编辑core/Route.php,修改addRoute方法

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

    $middlewares = [];
    if ($middleware && is_array($middleware)) {
        $middlewares = $middleware;
    } else if ($middleware) {
        $middlewares[] = $middleware;
    }

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

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

编辑core/Router.php,修改如下方法

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

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

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

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

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

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

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

修改start方法

private function start(RouteItem $item, string $namespace, Request $request, Response $response): void {
    if ($item->cb instanceof \Closure) {
        ($item->cb)($request, $response);
    } else {
        [$controller, $method] = explode('@', $item->cb);
        $module = "$namespace\\$controller";
        new $module($method, $item->middleware, $request, $response);
    }
}

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

<?php
namespace core;


class Controller {
    public array $middlewares = [];


    public function __construct(string $method, array $middlewares, Request $request, Response $response) {
        $this->applyMiddleware(array_merge($this->middlewares, $middlewares), $method, $request, $response);
    }


    private function applyMiddleware(array $middlewares, string $method, Request $request, Response $response): void {
        if (!empty($middlewares)) {
            $middleware = array_shift($middlewares);
            $next = function () use ($middlewares, $method, $request, $response) {
                $this->applyMiddleware($middlewares, $method, $request, $response);
            };
            call_user_func_array([new $middleware(), 'handle'], [$request, $response, $next]);
        } else {
            $this->{$method}($request, $response);
        }
    }
}

新建 app/middleware/Route.php,内容如下

<?php
namespace app\middleware;

use core\Request;
use core\Response;


class Route {
    public function handle(Request $request, Response $response, \Closure $next): void {
        echo 'Route(路由) 中间件 call before<br>';
        $next();
        echo 'Route(路由) 中间件 call after<br>';
    }
}

编辑route/user.php,为login路由添加中间件

$router->get('login', 'User@login', \app\middleware\Route::class);
$router->get('logout', 'User@logout');

测试

浏览器访问http://phpapi.com/user/login或者http://phpapi.com/user/logout,这里随机模拟了登录判断

当登录成功时,会输出

All(全局) 中间件 call before
Group(路由分组) 中间件 call before
User(控制器) 中间件 call before
Route(路由) 中间件 call before
Route(路由) 中间件 call after
User(控制器) 中间件 call after
Group(路由分组) 中间件 call before
All(全局) 中间件 call after
from /user/login

当登录失败时,会输出

All(全局) 中间件 call before
Group(路由分组) 中间件 call before
All(全局) 中间件 call after
请先登录

可以看出,目前中间件的执行顺序是全局->路由分组->控制器->路由

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

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