У меня есть следующий код для сопоставления маршрута с именем хоста;
'router' => [
'router_class' => 'Zend\Mvc\Router\Http\TranslatorAwareTreeRouteStack',
'routes' => [
'website' => [
'type' => 'hostname',
'may_terminate' => true,
'options' => [
'route' => ':locale.domain.:tld',
'constraints' => [
'language' => '(nl|en)',
'tld' => '(dev|org)',
],
],
]
],
],
И некоторые маршруты, чтобы соответствовать URI.
Так что в Dev я могу иметь такие маршруты, как en.domain.dev
а также nl.domain.dev
, Перевод маршрута также работает как шарм, но тогда возникают мои «проблемы»
1. Соберите URL
Для каждого URL мне сейчас нужно locale
а также tld
переменная. Для этого я делаю <?= $this->url('website/languages', [], true); ?>
, но это делает его беспорядком. Потому что я хочу использовать только TLD и локаль текущего маршрута.
Поэтому я пришел с решением расширить помощник по просмотру URL. И установить locale
а также tld
параметр, когда он не был установлен в соответствии с маршрутом. Это сработало для 1 «незначительной» проблемы, см. 2. Но мне было интересно, есть ли лучшее решение для этого.
2. 404 пага
В 1 я использую текущий маршрут, чтобы получить locale
/tld
собрать URL это все работает, за исключением 404 страницы. Потому что, чем нет маршрута, очевидно.
Я начал копать arround и когда я нашел роутер (из service locator
). Я пытался найти маршрут для website
он только вернулся Zend\Mvc\Router\Http\Part
,
protected $route
был Zend\Mvc\Router\Http\Hostname
который не доступен. Так что не повезло.
Единственный способ, которым я получил маршрут Hostname, состоял в том, чтобы создать его сам, чего я действительно не хочу делать.
Итак, вопрос в том, как легко использовать параметры имени хоста и получить параметры имени хоста на странице 404?
Я знаю, что, например, test.domain.test не будет соответствовать имени хоста и предоставит неверное имя хоста, но это вопрос Nginx. Поэтому Nginx позаботится о том, чтобы имя хоста всегда было правильным
Ну, я продолжал искать и думать и пришел с «решением».
Решать 2. Я создал слушатель, который слушает на MvcEvent::EVENT_DISPATCH_ERROR
,
Код;
// use are above the class declaration
use Zend\Mvc\Router\Http\TranslatorAwareTreeRouteStack;
use Zend\EventManager\AbstractListenerAggregate;
use Zend\EventManager\EventManagerInterface;
use Zend\Http\PhpEnvironment\Request;
use Zend\Mvc\Router\Http\RouteMatch;
use Zend\Mvc\MvcEvent;
public function onDispatchError(MvcEvent $event)
{
if (is_null($event->getRouteMatch())) {
$router = $event->getRouter();
$request = $event->getRequest();
if ($router instanceof TranslatorAwareTreeRouteStack && $request instanceof Request) {
$match = $router->getRoute('website')->match($request, strlen($request->getUri()->getPath()), array(
'translator' => $router->getTranslator(),
));
if ($match instanceof RouteMatch) {
$match->setMatchedRouteName('website');
$event->setRouteMatch($match);
}
}
}
}
Что оно делает;
проверить, есть ли совпадение маршрута, если нет, то это 404
проверить $router
является TranslatorAwareTreeRouteStack
и $request
это HttpRequest
проложить маршрут для website
(это маршрут для имени хоста`
тогда это соответствует ему (хитрость в том, что смещение установлено, поэтому проверяется только имя хоста)
устанавливает имя, соответствующее маршруту (если не установлено, пусто, что приведет к проблемам)
затем в событие вводится сопоставление маршрута
Решать 1. Теперь у меня всегда был доступ к route match
чтобы я мог творить магию. Я продлил url viewhelper
,
public function __invoke(
$name = null,
$params = array(),
$options = array(),
$reuseMatchedParams = false
) {
if ($this->routeMatch instanceof RouteMatch) {
foreach(['locale', 'tld'] as $key) {
if (!array_key_exists($key, $params)) {
$params[$key] = $this->routeMatch->getParam($key);
}
}
}
// This is needed for the magic that can happen when `reuseMatchedParams` is used at the third position
if (is_bool($options)) {
$reuseMatchedParams = $options;
$options = array();
}
return parent::__invoke(
$name,
$params,
$options,
$reuseMatchedParams
);
}
Не самый элегантный метод, но пока он работает
Других решений пока нет …