Рассмотрим варианты организации route в Silex.
Первый Вариант.
самый простой, первым показан в документации Silex
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
$app->post('/feedback', function (Request $request) {
$message = $request->get('message');
mail('feedback@yoursite.com', '[YourSite] Feedback', $message);
return new Response('Thank you for your feedback!', 201);
});
$app->post(), также возможны варианты $app->get(), $app->delete(), $app->put(), $app->match() при данном варианте желательно дописывать ->method('PUT|POST')
Использование переменных
$app->get('/blog/{id}', function ($id) {
...
});
Самый просто пример, мы единственное ожидаем любое значение id и метод GET.
$app->get('/blog/{postId}/{commentId}', function ($commentId, $postId) {
...
})
->assert('postId', '\d+')
->assert('commentId', '\d+');
Oтличается от предыдущего, только наличием нескольких переменных, но также ->assert('postId', '\d+') указано что именно мы ожидаем в переменных а именно только цифры.
$app->get('/blog/{id}', function (Application $app, Request $request, $id) {
...
})
->value('id', 1);
На данном варианте показано что возможно кроме переменных передавать и в какой последовательности, ->value('id', 1); уже указано значение по умолчанию, то есть мы можем ничего не передавать в запросе.
$app->get('/user/{id}', function ($id) {
// ...
})
->convert('id', function ($id) { return (int) $id; })
->bind('get_user');
$userProvider = function ($id) {
return new User($id);
};
$app->get('/user/{user}', function (User $user) {
// ...
})->convert('user', $userProvider);
Теперь мы еще добавили функционал который ->convert('id', function ($id) { return (int) $id; }) конвертирует данные которые приходят из запроса, а ->bind('get_user') дает роуту название чтобы было возможно его использовать при генерации URL в PHP $app['url_generator']->generate('get_user') и Twig {{ url('get_user', {'id': '1'}) }}. Далее просто один из примеров конвертации приходящих данных.
плюсы:
- все просто, организовывается в одном файле
минусы:
- при разработке в группе возможны пересечения путей
- при расширении необходимо дописывать функционал пути в тот же файл
Второй Вариант.
Route организовывается также, единственное мы перенесем контролер в отдельный файл.
//routes.php
$app->get('/', 'Controllers\Homepage::index');
//Controllers/Homepage.php
namespace Controllers
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
class Homepage
{
public function index(Request $request, Application $app)
{
...
}
}
Этот вариант просто расширяет первый, тоесть возможно использовать все что есть в первом варианте.
плюсы:
- Все плюсы Первого варианта
- Вынесение Контролеров в отдельных файл, облегчает разработку
минусы:
- Все минусы первого варианта
Вариант Третий.
В данном случае мы создаем отдельно контролеры, и добавляем в общий роутер, этот случай мало отличается от Второго, но тут возможно разделение роутов, в разные файлы, просто при инициализации приложения, мы имеем возможность дописывать префикс чтобы было меньше пересечений.
$app['controllers_factory']
->post('/home', 'Controllers\Homepage::index')
->bind("home_index");
$app->mount($prefix, $routes);
Использование переменных аналогично Первому случаю. Данный вариант аналогичен
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
$routeCollection = new RouteCollection();
$route = new Route('/home', array('_controller' => 'Controllers\Homepage::index'));
$route->setMethods('post');
$routeCollection->add('home_index', $route);
$app['routes']->addCollection($routeCollection);
плюсы:
- все разделено, возможность разрабатывать независимые модули для приложения
минусы:
- При разработке командой, возможен порог для подключения нового участника(введение в архитектуру всего приложения)
Четвертый Вариант.
Такой вариант привычен разработчикам на Symfony 2. Поэтому если вы желаете его использовать то возможно вы выбрали не тот Framework для своего приложения.
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Routing\Loader\YamlFileLoader;
use Symfony\Component\Routing\RouteCollection;
use Silex\Application;
$app = new Application();
$loader = new YamlFileLoader(new FileLocator(__DIR__ . '/сonfig'));
$collection = $loader->load('routes.yml');
$app['routes']->addCollection($collection);
Мы вынесли все роутеры в отдельный файл routes.yml, есть варианты PhpFileLoader и XmlFileLoader.
# config/routes.yml
home:
path: /
defaults: { _controller: 'Controllers\Homepage::index' }
hello:
path: /hello/{name}.{_format}
defaults: { _controller: 'Controllers\Homepage::hello', name: 'andrey', _format: html }
requirements:
name: \w+
_format: html|rss
methods: [POST]
api:
prefix: /api
resource: api.yml
# config/api.yml
api.list:
path: /list
defaults: { _controller: 'Controllers\Api::list' }
Доступны все возможности как и в первых трех случаях, но они все вынесены в файл конфигурации. Подробнее можно узнать на сайте Symfony
<?php
// Controllers/Homepage.php
namespace Controllers;
use Symfony\Component\HttpFoundation\Response;
use Silex\Application;
class Homepage
{
public function index()
{
return new Response("Homepage::index");
}
public function hello(Application $app, $name)
{
return new Response("Hello" . $app->escape($name));
}
}
плюсы:
- все разделено, возможность разрабатывать независимые модули для приложения
- все настройки routes в файле конфигов
минусы:
- Подключение дополнительных библиотек.
- Необходимость кешировать готовый функционал.
- нельзя использовать Route\SecurityTrait по умолчанию, прийдется писатьсвой загрузчик.
Выводы.
Есть много возможностей использование Route в Silex, Зависит от контекста задачи какой вам больше подходит в данном варианте.