По моему скромному мнению, Silex великолепен. Идеально создавать прототипы, но когда наше приложение растет, оно превращается в беспорядок. Это было то, что я думал до прошлого месяца, когда я присутствовал на большом разговоре о Silex с Хавьером Эгилузом. ХОРОШО. Масштабирование Silex это не то же самое, что с приложением Symfony, но это возможно.
Создать приложение Silex с помощью composer довольно просто:
{ "require": { "silex/silex": "1.0.*" }, "minimum-stability": "dev" }
Но есть и лучший способ. Мы можем использовать скелет Фабьена Потенциера . С этим скелетом мы можем лучше организовать наш код.
Мы также можем использовать классы в качестве контроллеров вместо использования замыкания со всем кодом. У Игоря Видлера есть отличный пост об этом. Вы можете прочитать это здесь .
Сегодня я играю с Silex и хочу вам кое-что показать. Давайте начнем:
Возможно, вы знаете, что я большой поклонник Symfony Dependency Injection Container (вы можете прочитать об этом здесь и здесь ), но Silex использует Pimple. На самом деле приложение Silex расширяет класс Pimple. Моя идея заключается в следующем:
В посте Игоря мы видим, как использовать такие вещи:
$app->match('/video/{id}', 'Gonzalo123\ApiController::indexAction')->method('GET')->bind('video_info');
Моя идея — хранить эту информацию в служебном контейнере (мы будем использовать DIC Symfony) Например, здесь мы можем увидеть наши rout.yml:
routes: video_info: pattern: /video/{id} controller: Gonzalo123\ApiController::initAction requirements: _method: GET
Как мы видим, нам нужно реализовать одно расширение для псевдонима «маршруты». В этом примере мы реализуем только необходимые функции для файлов YAML.
<?php use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; class SilexRouteExtension implements ExtensionInterface { /** * Loads a specific configuration. * * @param array $config An array of configuration values * @param ContainerBuilder $container A ContainerBuilder instance * * @throws InvalidArgumentException When provided tag is not defined in this extension * * @api */ public function load(array $config, ContainerBuilder $container) { } /** * Returns the namespace to be used for this extension (XML namespace). * * @return string The XML namespace * * @api */ public function getNamespace() { } /** * Returns the base path for the XSD files. * * @return string The XSD base path * * @api */ public function getXsdValidationBasePath() { } /** * Returns the recommended alias to use in XML. * * This alias is also the mandatory prefix to use when using YAML. * * @return string The alias * * @api */ public function getAlias() { return "routes"; } }
И теперь нам нужно только подготовить DIC. Согласно рекомендации Фабьена в его скелете Silex, нам нужно только изменить файл src / controllers.php
<?php use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; // Set up container $container = new ContainerBuilder(); $container->registerExtension(new SilexRouteExtension); $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../config/')); // load configuration $loader->load('routes.yml'); $app['container'] = $container; $app->mount('/api', include 'controllers/myApp.php'); $container->compile(); $app->error(function (\Exception $e, $code) use ($app) { if ($app['debug']) { return; } $page = 404 == $code ? '404.html' : '500.html'; return new Response($app['twig']->render($page, array('code' => $code)), $code); });
и теперь мы определяем config / rout.yml
routes: video_info: pattern: /video/{videoId} controller: Gonzalo123\ApiController::initAction requirements: _method: GET
И, наконец, магия в наших контроллерах / myApp.php:
<?php $myApp = $app['controllers_factory']; foreach ($container->getExtensionConfig('routes')[0] as $name => $route) { $controller = $myApp->match($route['pattern'], $route['controller']); $controller->method($route['requirements']['_method']); $controller->bind($name); } return $myApp;
Класс для этого примера: src / Gonzalo123 / ApiController.php
<?php namespace Gonzalo123; use Silex\Application; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\JsonResponse; class ApiController { public function initAction(Request $request, Application $app) { return new JsonResponse(array(1, 1, $request->get('id'))); } }
Как вы можете видеть, идея состоит в том, чтобы использовать классы в качестве контроллеров, определить их в контейнере службы и создать необходимый код Silex, повторяющийся в конфигурации. Что вы думаете?