段 class 上带有子路由的 ZF3 可选参数不想匹配

ZF3 optional parameter with child routes on Segment class doesn't want to match

我想创建带有可选 [lang] 参数的路由,该参数将用于设置应用程序语言,如下所示:

带有默认语言参数的示例(例如 EN)

domain.tld/
domain.tld/users
domain.tld/contacts
etc.

新语言参数示例(DE for examle)

domain.tld/de
domain.tld/de/users
domain.tld/de/contacts
etc.

这是我的路线配置:

'router' => [
    'routes' => [
        'site' => [
            'type' => Segment::class,
            'options' => [
                'route' => '[/:lang]',
                'constraints' => [
                    'lang' => '[a-z]{2}',
                ],
                'defaults' => [
                    'controller' => Controller\IndexController::class,
                    'action' => 'index',
                    'lang' => 'en',
                ],
            ],
            'may_terminate' => true,
            'child_routes' => [
                'home' => [
                    'type' => Literal::class,
                    'options' => [
                        'route' => '/',
                        'defaults' => [
                            'controller' => Controller\IndexController::class,
                            'action' => 'index',
                        ],
                    ],
                    'may_terminate' => true,
                ],
                'application' => [
                    'type' => Segment::class,
                    'options' => [
                        'route' => '/application[/:action]',
                        'defaults' => [
                            'controller' => Controller\IndexController::class,
                            'action' => 'index',
                        ],
                    ],
                    'may_terminate' => true,
                ],
            ],
        ],
    ],
]

当我在 url 中有 lang 参数时,一切都很好。但是当我尝试打开 "default" lang 而不在路径中指定它时(例如。tld/application/test)它给我 404 错误。

我发现从Segmentclass转换后的最终正则表达式是(\G(?:/(?P<param1>([a-z]{2})))?),路径是/application/test。当 preg_match 在 Segment.php:385 上执行时,它 return 匹配以下值:

[
    '0' => '/ad',
    'param1' => 'ad',
    '1' => 'ad',
],

这显然是错误的行为。我的语言设置为 "ad" 而不是打开 application/test 操作。我测试了大约 10 个正则表达式但没有成功......(例如 ^[a-z]{2}$)。

我做错了什么?

你得到 404 因为 URL 不匹配 site 路由,所以 site 的子路由被跳过。
试试这个:

        'home' => [
            'type' => Segment::class,
            'options' => [
                'route' => '/[:lang/]',
                'constraints' => [
                    'lang' => '(en|de)?',
                ],
                'defaults' => [
                    'controller' => Controller\IndexController::class,
                    'action' => 'index',
                    'lang' => 'en',
                ],
            ],
            'may_terminate' => true,
            'child_routes' => [
                'application' => [
                    'type' => Segment::class,
                    'options' => [
                        'route' => 'application[/:action]',
                        'defaults' => [
                            'controller' => Controller\IndexController::class,
                            'action' => 'index',
                        ],
                    ],
                ],
            ],
        ]

如果您不提供 lang 参数,那么它将使用默认值(在我的示例中为 en)参数。
示例:

example.tld/application/test

  • langen
  • controllerIndexController
  • actiontest (testAction())

example.tld/de/application/test

  • langde
  • controllerIndexController
  • actiontest (testAction())