【问题标题】:Host name routing in Zend ExpressiveZend Expressive 中的主机名路由
【发布时间】:2017-02-01 16:46:07
【问题描述】:

Zend Expressive 有一个 Aura.Router、FastRoute 和 zend-mvc 路由器的适配器,并且路由可以轻松匹配方法和路径:

<?php
$app->get('/foo', $middleware);

使用zend-mvc Router 组件可以匹配主机名:

<?php
use Zend\Mvc\Router\Http\Hostname;

$route = Hostname::factory([
    'route' => ':subdomain.example.com/foo',
    'constraints' => [
        'subdomain' => 'api',
    ],
]);

$router->addRoute('foo', $route);

Symfony Routing Component 也可以做到这一点:

<?php
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;

$route = new Route(
    '/foo', // path
    array('_controller' => 'SomeController'), // default values
    array('subdomain' => 'api'), // requirements
    array(), // options
    '{subdomain}.example.com', // host
    array(), // schemes
    array() // methods
);

$routes = new RouteCollection();
$routes->add('foo', $route);

所以,我希望能够使用 Expressive 做类似的事情,并根据子域将请求分派到不同的中间件:

// dispatch the requiest to ApiMiddleware
$app->get(':subdomain.example.com/foo', $ApiMiddleware, ['subdomain' => 'api']);

// dispatch the requiest to WebMiddleware
$app->get(':subdomain.example.com/foo', $WebMiddleware, ['subdomain' => 'www']);

提前致谢!

【问题讨论】:

  • 我认为没有任何路由器支持这一点。你可以做的是为 Symfony 路由器组件编写你自己的桥接器。它有一些其他人所缺少的不错的功能。
  • 主机名路由有PR

标签: php zend-framework symfony-routing zend-router mezzio


【解决方案1】:

你为什么不创建一个新的中间件来提取请求并选择接下来应该在管道中调用哪个中间件?

你可以这样做:

应用程序\中间件\DeciderMiddleware

<?php

namespace Application\Middleware;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

class DeciderMiddleware
{
    protected $apiMiddleware;
    protected $webMiddleware;

    public function __construct(
        callable $apiMiddleware,
        callable $webMiddleware
    ) {
        $this->apiMiddleware = $apiMiddleware;
        $this->webMiddleware = $webMiddleware;
    }

    public function __invoke(
        ServerRequestInterface $request,
        ResponseInterface $response,
        callable $next = null
    ) {
        if (strpos($request->getUri()->getHost(), 'api.') === 0) {
            return ($this->apiMiddleware)($request, $response);
        }

        if (strpos($request->getUri()->getHost(), 'www.') === 0) {
            return ($this->webMiddleware)($request, $response);
        }

        return $next($request, $response);
    }
}

config/autoload/middleware-pipeline.global.php

<?php

return [
    'dependencies' => [
        'factories' => [
            Application\Middleware\DeciderMiddleware::class => Application\Middleware\DeciderMiddlewareFactory::class
        ],
    ],
    'middleware_pipeline' => [
        'always' => [
            'middleware' => [
                Application\Middleware\DeciderMiddleware::class
            ],
            'priority' => 10000,
        ],
    ],
];

您唯一要做的就是在 DeciderMiddlewareFactory 中定义 apiMiddleware 和 webMiddleware 并使用这些参数初始化 DeciderMiddleware-object。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-30
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 2011-04-15
    • 1970-01-01
    • 1970-01-01
    • 2013-11-10
    相关资源
    最近更新 更多