По моему скромному мнению, 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, повторяющийся в конфигурации. Что вы думаете?