Symfony 2 Как динамически добавлять маршруты с доступом к объекту запроса

Фон:

Я пытаюсь условно загрузить маршруты на основе запроса узла. У меня есть настройка базы данных, в которой есть хосты, которые сопоставляются с шаблонами. Если пользователь заходит с хоста A и который использует шаблон TA Я хочу загрузить маршруты для этого шаблона. Если они приходят от хозяина B затем загрузите маршруты для этого шаблона (TB).

Я должен сделать это потому, что каждый шаблон будет использовать много маршрутов. Однако есть несколько уникальных маршрутов для данного шаблона.

Было бы хорошо ограничить каждый шаблон маршрутов для данного хоста, за исключением того, что существует буквально 1000 хостов.

Что я попробовал:

Я пробовал собственный загрузчик маршрутов, как описано в документации здесь:

http://symfony.com/doc/current/cookbook/routing/custom_route_loader.html

Однако, когда я настраиваю службу и пытаюсь внедрить "@request" конструктор терпит неудачу, потому что $ request является нулем

services:
acme_demo.routing_loader:
class: Acme\DemoBundle\Routing\ExtraLoader
arguments: ["@request"]
tags:
- { name: routing.loader }

Учебный класс:

<?php
namespace: Acme\DemoBundle\Routing;
use Symfony\Component\HttpFoundation\Request;
class ExtraLoader
{
protected $request;

public function __construct(Request $request)
{
$this->request = $request;
}
// ...
}

Это также не работает, если я пытаюсь переключиться "@request" за "@service_container" затем позвоните

$this->container->get('request');

Самое близкое, что я получил к этой работе, было следующее руководство, найденное здесь:

http://marcjschmidt.de/blog/2013/11/30/symfony-custom-dynamic-router.html

Проблема, которую я имею с этим, я пытаюсь использовать annotation на контроллере, и я не могу получить Symfony\Component\Routing\Loader\AnnotationFileLoader за работой.

0

Решение

Хорошо, я наконец-то разобрался с рабочим решением, это смесь нескольких из упомянутых выше руководств.

Я использую слушатель запроса ядра:

services:
website_listener:
class: NameSpace\Bundle\EventListener\WebsiteListener
arguments:
- "@website_service"- "@template_service"- "@sensio_framework_extra.routing.loader.annot_dir"- "@router"- "%admin_domain%"tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 33 }

Слушатель:

<?php
namespace NameSpace\WebsiteBundle\EventListener;

use NameSpace\TemplateBundle\Service\TemplateService;
use NameSpace\WebsiteBundle\Service\WebsiteService;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader;
use Symfony\Component\HttpKernel\EventListener\RouterListener;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Component\PropertyAccess\PropertyAccess;

class WebsiteListener
{

/**
* @var WebsiteService
*/
protected $websiteService;

/**
* @var TemplateService
*/
protected $templateService;

/**
* @var AnnotationDirectoryLoader
*/
protected $loader;

/**
* @var Router
*/
protected $router;

/**
* @var string
*/
protected $adminDomain;

public function __construct(WebsiteService $websiteService, TemplateService $templateService, AnnotationDirectoryLoader $loader, Router $router, $adminDomain)
{
$this->websiteService = $websiteService;
$this->templateService = $templateService;
$this->loader = $loader;
$this->router = $router;
$this->adminDomain = $adminDomain;
}

public function loadRoutes()
{
$template = $this->templateService->getTemplateByAlias($this->websiteService->getWebsite()->getTemplate());

$routes = $this->loader->load($template['routes'],'annotation');
$allRoutes = $this->router->getRouteCollection();
$allRoutes->addCollection($routes);
}

public function onKernelRequest(GetResponseEvent $event)
{
try {
$this->websiteService->handleRequest($event->getRequest());
$this->loadRoutes();
} catch(NotFoundHttpException $e) {
if($event->getRequest()->getHost() !== $this->adminDomain){
throw $e;
}
}

}
}

Ключевые части этого:

  • Loader — Я нашел "@sensio_framework_extra.routing.loader.annot_dir" в исходном коде. То, что загрузчик каталогов аннотаций, который Symfony использует по умолчанию, это тот, который я тоже хочу использовать. Но если вы хотите использовать другой загрузчик, есть другие доступные.
  • Router — Это то, что я использую, чтобы получить все текущие маршруты. НОТА что $allRoutes->addCollection($routes) звонок на отдельной линии. Я не уверен, почему это имеет значение, но назвать все это в 1 как не работало.
  • $template['routes'] это просто ссылка на контроллер пространства имен, которую вы использовали бы для добавления маршрутизации в вашем routing.yml. Что-то вроде: "@NamespaceBundle/Controller"
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]