Все привет! Сегодня мы будем говорить о небольшом, но довольно мощном фреймворке, созданном на основе компонентов Symfony - Silex. Как PHP разработчик, повидавший не мало, я давно слышал об этом маленьком чуде, но все как-то руки не доходили. Если вам нужно написать небольшой REST сервис, или небольшой проект, для которого полный пакет Symfony или другие фреймворки будут слишком громоздки, то отличным выбором станет Silex. Давайте посмотрим, что же он из себя представляет. Документацию можно почитать здесь. Она на английском языке, но мы же с вами разработчики! Английский нужно практиковать в обязательном порядке)))
Подготовка проекта
Чтобы написать простейшее приложение, нам понадобится всего один файл и несколько строчек кода, но прежде нам нужно скачать сам Silex. Можно скачать прямо с сайта разработчиков, но я использую composer для этого:
composer require silex/silex:~2.0
Для запуска проекта нам понадобится правильно сконфигурированный веб-сервер (подробно читайте здесь).
Для Apache нам нужно создать файл .htaccess со следующим содержимым:
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
#RewriteBase /path/to/app
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
</IfModule>
Если ваш проект лежит не в корне сервера, то раскомментируйте строчку RewriteBase, указав правильное значение пути к папке проекта.
Файл .htaccess помещаем в директорию с публичным доступом, обычно она носит имя web, в той же папке создаем файл bootstrap:
// web/index.php
require_once __DIR__.'/../vendor/autoload.php';
$app = new Silex\Application();
// ... definitions
$app->run();
Далее нам нужно создать маршрут для нашей первой страницы:
<?php
require_once __DIR__ . '/../vendor/autoload.php';
$app = new Silex\Application();
$app->get('/', function() use($app) {
return 'Hello, World!';
# можно вернуть объект ответа, как и в Symfony
# return new Symfony\Component\HttpFoundation\Response('Hello, world');
});
$app->run();
Как видно из примера выше, создание простого роута в Silex не представляет особой сложности. Доступны также методы POST, PATCH, DELETE, PUT. Вторым аргументом метод принимает коллбек, который представляет собой лямбда-функцию контроллера. Контроллер должен возвращать ответ, даже если это будет просто строка текста.
Запускаем сервер и смотрим на результат. Можно также воспользоваться встроенным php-сервером:
php -S localhost:8000
Попробуем сделать так, чтобы контроллер ничего не возвращал и посмотрим на результат:
<?php
require_once __DIR__ . '/../vendor/autoload.php';
$app = new Silex\Application();
$app->get('/', function() use($app) {
echo 'hello';
});
$app->run();
Видим, что произошла какая-то ошибка
Включим дебаг режим в приложении и посмотрим, что получится:
$app['debug'] = true;
Добавим теперь динамический роут в наше приложение, передавая динамический параметр в качестве параметра коллбека:
$app->get('/hello/{name}', function($name) use($app) {
return "Hello, {$name}";
});
Если вы хотите, чтобы контроллер был доступен для всех HTTP методов, используйте метод объекта приложения match:
$app->match('/http-methods', function() {
return 'This controller can be executed by all HTTP methods.';
});
$app->match('/http-methods/restricted-get', function() {
return 'This controller can be executed only by GET HTTP method.';
})
->method('GET');
$app->match('/http-methods/restricted-put-post', function() {
return 'This controller can be executed only by PUT and POST HTTP methods.';
})
->method('PUT|POST');
Есть еще одна вкусная штука в роутинге - конвертеры. Я приведу пример, чтобы вы поняли, о чем идет речь:
$app->get('/user/{id}', function($id) use($app) {
// ...
})
->convert('id', function($id) { return (int) $id });
$postProvider = function ($id) {
return new Post($id);
};
$app->get('/post/{post}', function (Post $post) {
// ...
})
->convert('post', $postProvider);
Таким образом, если вы хотите получить в контроллере сразу объект, а не просто переменную идентификатора или сделать с параметром какие-либо преобразования до того, как он попадет в контроллер, используйте возможность конвертации с помощью метода convert.
Кроме того, система роутинга в Silex предлагает привязывать условия к роуту (conditions), ставить ограничения (requirements). Существует возможность настроить эти вещи глобально в приложении для всех контроллеров. Но это материал для отдельной статьи. Для более углубленного изучения возможностей роутинга в Silex обратитесь к документации.
2. Подключение поставляемых service провайдеров
Вы можете создать свои провайдеры, зарегистрировать их и использовать в приложении. Подробнее об этом читайте здесь.
Silex поставляется со значительным числом service провайдеров, которые расширяют его возможности и позволяют подключить сторонние библиотеки, такие как Twig, SwiftMailer, Doctrine и другие.
Провайдеры оформлены в виде трейтов и для их подключения необходимо переопределить объект Silex\Application. Создадим новый класс Application в папке app/:
<?php
// app/Application.php
class Application extends Silex\Application
{
use \Silex\Application\TwigTrait;
//...
}
Для того, чтоб это все заработало, нам нужно установить необходимые зависимости:
composer require symfony/twig-bridge # интеграция Twig с компонентами Symfony
composer require twig/twig
Соответственно, теперь нам нужно создать объект приложения и зарегистрировать провайдер:
<?php
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/../app/Application.php';
$app = new Application();
$app['debug'] = true;
$app->register(new \Silex\Provider\TwigServiceProvider(), array(
'twig.path' => __DIR__ . '/app/Resources/views'
));
// ...
$app->run();
Теперь можно пользоваться шаблонизатором. Обратите внимание, что при регистрации провайдера мы указали путь к директории с файлами представлений. Теперь создадим файл представления для нашего контроллера и внесем изменения в контроллер:
// app/Resources/views/hello.html.twig
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>First Silex application!</title>
</head>
<body>
<p>Hello, {{ name }}!</p>
</body>
</html>
// web/index.php
// ...
$app->get('/hello/{name}', function($name) use($app) {
return $app['twig']->render('hello.html.twig', array(
'name' => $name
));
});
// ...
Запускаем приложение и видим все ту же строчку с приветствием, но теперь уже на экране отображается наш код из файла представления.
Ну вот мы вкратце познакомились с Silex. Надеюсь, теперь у вас не возникает вопросов, почему он достаточно мощный, хоть может быть и легковесным для простых задач. Мы создали свое первое приложение, с использованием Twig в качестве шаблонизатора. В следующей статье, посвященной Silex, мы поговорим об одном из способов организации кода в приложении и настроим еще несколько важных провайдеров. А на этом позвольте откланяться и до новых встреч!