CakePHP 3.6:路由和中间件

问题描述 投票:1回答:1

我有一个cakephp plugin,可以创建图像缩略图。 目前,缩略图由控制器的动作“提供”,该控制器将文件作为响应返回(here)。

这是路线:

Router::plugin(THUMBER, ['path' => '/thumb'], function (RouteBuilder $routes) {
    $routes->get('/:basename', ['controller' => 'Thumbs', 'action' => 'thumb'], 'thumb')
        ->setPatterns(['basename' => '[\w\d=]+'])
        ->setPass(['basename']);
});

所以url是这些(缩略图基名被编码):

/thumb/ZDc1NTYyMGY1N2VmMzRiNTQyZjE0NTY2Mjk0YWQ2NTFfNGIyYTBkMjVhMTdjZTdjN2E4MjVjY2M1YWU1ODNhMzcuZ2lm

现在我正在尝试用中间件替换控制器。 这很简单,因为基本上它会像AssetMiddleware一样工作,而__invoke()方法几乎就像旧的动作方法:

class ThumbnailMiddleware
{
    use ThumbsPathTrait;

    public function __invoke($request, $response, $next)
    {
        if ($request->getParam('_name') !== 'thumb' || !$request->getParam('basename')) {
            return $next($request, $response);
        }

        $file = $this->getPath(base64_decode($request->getParam('basename')));

        if (!is_readable($file)) {
            throw new ThumbNotFoundException(__d('thumber', 'File `{0}` doesn\'t exist', $file));
        }

        $response = $response->withModified(filemtime($file));

        if ($response->checkNotModified($request)) {
            return $response;
        }

        return $response->withFile($file)->withType(mime_content_type($file));
    }
}

这非常有效。 问题是它现在有效,因为这个中间件采用控制器的路径并“拦截”请求,“解析”它而不通过控制器(参见__invoke()方法的前三行)。

现在我想重写该路由并从控制器解开它,我应该完全从插件中消除它。

显然它的效果很好(第二个参数是null):

$routes->get('/:basename', null, 'thumb')
    ->setPatterns(['basename' => '[\w\d=]+'])
    ->setPass(['basename']);

或者我可以调用RouteBuilder::fallback()方法并分析请求的url(就像AssetMiddleware一样)。

但我想知道是否有办法将路由仅链接到中间件并明确地用于中间件。或者,如果没有,最好的方法是什么。我知道我可以将“中间件应用于特定的路由范围”(cookbook),所以我想知道这是否是正确的公式:

Router::plugin(THUMBER, ['path' => '/thumb'], function (RouteBuilder $routes) {
    $routes->registerMiddleware('thumbnail', new ThumbnailMiddleware);
    $routes->applyMiddleware('thumbnail');
    $routes->get('/:basename', null, 'thumb')
        ->setPatterns(['basename' => '[\w\d=]+'])
        ->setPass(['basename']);
});
cakephp cakephp-3.x
1个回答
2
投票

好吧,你不需要将任何默认值传递给路由,所以从这个角度看它是正确的,路由不会“绑定”到控制器。如果您的中间件不会拦截请求,那么事情最终将被抛出MissingControllerException,因为调度程序会将null作为控制器名称。由此产生的错误消息可能会有点误导,因为不会包含控制器名称。

你在那里做的将导致你的中间件应用于/thumb范围内的所有路由,所以如果有任何其他路由,那么你的中间件将需要进行参数检查。您可以通过将中间件应用于该特定路由而不是路由构建器来进一步限制事物:

// $routes->applyMiddleware('thumbnail'); // don't do that
$routes
    ->get('/:basename', null, 'thumb')
    ->setPatterns(['basename' => '[\w\d=]+'])
    ->setPass(['basename'])
    ->setMiddleware(['thumbnail']); // do this instead

这样,您的中间件只会针对该特定路由调用。

© www.soinside.com 2019 - 2024. All rights reserved.