Индивидуальная конфигурация маршрута с Silex

Я знаю, что в основе Silex лежит подход, при котором вся логика приложения в одном файле. Но в моем приложении можно будет иметь более двадцати контроллеров. Вот и хочу иметь удобную карту для управления роутером.

Мой вопрос заключается в поиске решения, в котором я смог бы сделать роутер отдельным файлом. В лучшем случае файл должен быть типа YAML:

# config/routing.yml

_home:
    pattern: /
    defaults: { _controller: MyProject\Controller\MyController::index }

Но натив тоже хороший случай (для меня):

$routes = new RouteCollection();

$routes->add(
    'home',
    new Route('/', array('controller' => 'MyProject\Controller\MyController::index')
));

return $routes;

Проблема второго случая в том, что я должен использовать функцию match() для каждого правила маршрутизации. Это совсем не ясно.

Каковы пути решения этой проблемы? Условие состоит в том, что я хочу использовать существующий API Silex или компоненты Symfony2.

Небольшое примечание:

Я не использую ControllerProviderInterface для своих классов контроллеров. Это независимые классы.


person Yury    schedule 03.02.2013    source источник
comment
Когда у вас так много контроллеров, это признак того, что вам следует использовать полностековый фреймворк вместо silex.   -  person Maerlyn    schedule 04.02.2013
comment
@maerlyn silex — это микрофреймворк, это не значит, что его нельзя использовать для больших проектов. Это означает, что вам нужно принимать собственные решения о том, как организовать свой проект. См. дополнительную информацию: igor.io/2012/11/09/scaling- силекс.html   -  person Wouter J    schedule 04.02.2013
comment
@WouterJ Я согласен, и я тоже использовал силекс для больших проектов, я просто хотел, чтобы ОП рассмотрел и эту альтернативу.   -  person Maerlyn    schedule 04.02.2013
comment
Привет @Stmol, ты видел мой ответ? У меня было то же самое требование, что и у вас, я понял это самым простым способом :)   -  person Jimbo    schedule 15.08.2013


Ответы (4)


Во-первых, основа Silex не в том, чтобы вы помещали все в один файл. Основа Silex заключается в том, что вы создаете свою собственную «инфраструктуру», свой собственный способ организации приложений.

«Используйте silex, если вам удобно принимать все свои собственные архитектурные решения, и Symfony2 с полным стеком, если нет». -- Дастин Уиттл

Подробнее об этом читайте в этой записи в блоге, созданной создателем Silex.


Как решить вашу проблему

В основном вам нужно проанализировать файл Yaml и получить настройки pattern и defaults._controller из каждого анализируемого маршрута.

Чтобы проанализировать файл Yaml, вы можете использовать компонент Yaml Symfony2. Вы получаете массив, который можно использовать для добавления маршрута в Silex:

// parse the yaml file
$routes = ...;
$app = new Silex\Application();

foreach ($routes as $route) {
    $app->match($route['pattern'], $route['defaults']['_controller']);
}

// ...
$app->run();
person Wouter J    schedule 03.02.2013

Я подумал, что добавлю сюда свой метод, поскольку, хотя другие могут работать, на самом деле простого решения нет. Добавление FileLocator/YamlFileLoader добавляет объемную нагрузку, которую я не хочу использовать в своем приложении, просто для чтения/анализа файла yaml.

Композитор

Во-первых, вам нужно будет включить соответствующие файлы. Компонент Symfony YAML, а также очень простой и полезный поставщик услуг конфигурации от кто-то, кто активно работает над Silex.

"require": {
    "symfony/yaml": "~2.3",
    "igorw/config-service-provider": "1.2.*"
}

Файл

Допустим, ваш файл маршрутов выглядит так (routes.yml):

config.routes:
  dashboard:
    pattern:  /
    defaults: { _controller: 'IndexController::indexAction' }
    method:   GET

Регистрация

Индивидуально зарегистрируйте каждый файл yaml. Первый ключ в файле — это имя, которое будет доступно в вашей переменной $app (обрабатывается локатором сервиса pimple).

$this->register(new ConfigServiceProvider(__DIR__."/../config/services.yml"));
$this->register(new ConfigServiceProvider(__DIR__."/../config/routes.yml"));
// any more yaml files you like

Маршруты

Вы можете получить эти маршруты, используя следующее:

$routes = $app['config.routes']; // See the first key in the yaml file for this name
foreach ($routes as $name => $route)
{
    $app->match($route['pattern'], $route['defaults']['_controller'])->bind($name)->method(isset($route['method'])?$route['method']:'GET');    
}

->bind() позволяет вам «именовать» ваши URL-адреса, которые будут использоваться, например, в twig.
->method() позволяет указать POST | ПОЛУЧАТЬ. Вы заметите, что по умолчанию я установил значение «GET» с тройным кодом, если в маршруте не указан метод.

person Jimbo    schedule 05.08.2013

Хорошо, я так решил.

Этот метод является частью моего приложения и вызывается перед run():

# /src/Application.php

...

protected function _initRoutes()
{
    $locator = new FileLocator(__DIR__.'/config');
    $loader = new YamlFileLoader($locator);

    $this['routes'] = $loader->load('routes.yml');
}

Класс приложения мой собственный и расширяет Silex\Application.

Конфигурационный файл:

# /src/config/routes.yml
home:
    pattern: /
    defaults: { _controller: '\MyDemoSite\Controllers\DefaultController::indexAction' }

Он отлично работает для меня!

UPD:

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

$this['routes']->addCollection($loader->load('routes.yml'));

Более гибкий.

person Yury    schedule 05.02.2013

Вы можете расширить службу routes (которая является RouteCollection) и загрузить файл YAML с FileLocator и YamlFileLoader:

use Symfony\Component\Config\FileLocator;
use Symfony\Component\Routing\Loader\YamlFileLoader;

$app->extend('routes', function($routeCollection) {

    $locator    = new FileLocator([__DIR__ . '/../config']);
    $loader     = new YamlFileLoader($locator);
    $collection = $loader->load('routes.yml');

    $routeCollection->addCollection($collection);

    return $routeCollection;

});

Однако вам понадобятся зависимости symfony/config и symfony/yaml.

person icecold_3000    schedule 08.11.2017