Варианты Routes в Silex

Рассмотрим варианты организации 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, Зависит от контекста задачи какой вам больше подходит в данном варианте.

Дополнительные источники

Scaling Silex applications (part II). Using RouteCollection

Читайте также:

Docker установка и настройка

При разработке используется множество технологий. К примеру данный блог использует php(Symfony 2), mongodb, elastic, nginx это основные но также используется nodejs к примеру для минификации css, js. При разработке приходится настраивать все технологии как показано в статье. Но что делать если проектов несколько или они используют разные технологии, например другой проект использует MySQL, или еще могут использовать разные версии php или других библиотек. Для разработки и поддержки проектов на разных технологиях можно использовать Виртуальную машину и поставить на нее к примеру centos, но это не совсем удобно, надо все равно настраивать подобное окружение как на сервере и на других машинах разработчиков. Мы будет использовать контейнеры, такие как Docker. Настроем блог разработчиков чтобы использовать Docker для разработки.

Как использовать произвольное хранилище пользователей в FOSUserBundle

Практически все используют FOSUserBundle в своих Symfony проектах т.к. он ускоряет разработку и обладает хорошим набором функциональности для управления пользователями. Бандл предоставляет несколько готовых реализаций хранилищ данных: Propel и несколько для Doctrine (ORM и ODM). Это здорово, но иногда возникает необходимость работы с другими хранилищами данных. FOSUserBundle достаточно гибок и позволяет реализовать, и использовать произвольное хранилище. Для того, чтобы использовать все возможности FOSUserBundle Вам достаточно будет написать свой менеджер пользователей под конкретного провайдера.

Интеграция Paysera в Symfony

Сегодня сложно представить себе серьезный проект, где не понадобилась бы интеграция с платежными системами. Не смотря на то что существует множество популярных систем и аггрегаторов, таких как PayPal, RBKMoney, Paymentwall, Robokassa и т.д., я хочу рассказать о Paysera. Это еще одна, довольно новая платежная система. Они позиционируют себя как выгодных с точки зрения комиссий за их услуги. Paysera позволяет вашим пользователям расплачиваться карточками, SMS и т.д. Интеграция довольно простая, однако имеет некоторые неочевидные моменты, которые я и хочу осветить.

Создание сайта “Обратный отсчет” на Symfony2

Мы иногда видим сайты с обратным отсчетом, проект стартует через … Его сделать достаточно просто, и не займет много времени. Мы воспользуемся проектом fdevs/coming-soon, который основан на Symfony2. Также будем сохранять введеный пользователями адреса электронной почтой в базу данных MongoDB. У нас есть настроенное рабочее окружение Osx, о настройке можно прочитать в статье Yosemite настройка рабочего окружения. Но главное версия php не меньше 5.4. В проекте можно также использовать реляционную базу данных типа MySQL. По умолчанию в проекте вообще не используется база данных, а введеный email отправляется на почту.

Yosemite настройка рабочего окружения.

После обновления OSx Yosemite, необходимо настроить рабочую систему. Мы установим и настроим пакеты php-fpm, nginx, mongo, nodejs. Для начала установим Xcode из App Store обновим консольные команды $ xcode-select --install и уберем apache из автозагрузки $ sudo launchctl unload /System/Library/LaunchDaemons/org.apache.httpd.plist . Так как у Apple не появилось своего менеджера пакетов будем использовать проверенный brew.