Cakephp 中多个主机的路由

Routing for multiple hosts in Cakephp

正如食谱所说:

Routes can use the _host option to only match specific hosts. You can use the *. wildcard to match any subdomain.

但是如果我想一次为多个主机设置相同的路由怎么办?

例如:

$routes->connect(
    '/images',        
    ['controller' => 'Images', 'action' => 'index']
)->setHost('images.example.com');

$routes->connect(
    '/images',        
    ['controller' => 'Images', 'action' => 'index']
)->setHost('images.example2.com');

$routes->connect(
    '/images',        
    ['controller' => 'Images', 'action' => 'index']
)->setHost('images.example3.com');

如果我必须设置几十个这样的路由,以上内容毫无意义。

理想情况是这样的:

$routes->connect(
    '/images',        
    ['controller' => 'Images', 'action' => 'index']
)->setHosts(['images.example.com','images.example2.com','images.example3.com']);

这是不支持的,您要么必须相应地设置多条路由,您可以简单地在一个循环中执行,并提供您的主机列表:

foreach (['images.example.com','images.example2.com','images.example3.com'] as $host) {
    $routes
        ->connect(
            '/images',        
            ['controller' => 'Images', 'action' => 'index']
        )
        ->setHost($host);
}

或者创建一个自定义路由 class 接受多个主机,或者可能是实际的正则表达式。后者可能会更容易,因为它不需要重新实现很多匹配的东西,比如:

src/Routing/Route/RegexHostRoute.php

namespace App\Routing\Route;

use Cake\Routing\Route\DashedRoute;

class RegexHostRoute extends DashedRoute
{
    public function match(array $url, array $context = []): ?string
    {
        // avoids trying to match the _host option against itself in parent::match()
        if (!isset($url['_host'])) {
            return null;
        }

        return parent::match($url, $context);
    }

    public function hostMatches(string $host): bool
    {
        return preg_match('^@' . $this->options['_host'] . '@$', $host) === 1;
    }
}

这应该允许设置像 images\.example[2-3]?\.com:

这样的主机
$routes
    ->connect(
        '/images',        
        ['controller' => 'Images', 'action' => 'index'],
        ['routeClass' => \App\Routing\Route\RegexHostRoute::class]
    )
    ->setHost('images\.example[2-3]?\.com');

另见