Возможно ли (и как)
Какой id нравится делать, чтобы загрузить различные шаблоны без изменения какого-либо контроллера.
ОБНОВИТЬ
Здесь не проблема обнаружения, это не имеет никакого отношения к symfony. Это можно сделать (загрузить другой шаблон) на уровне контроллера:
public function indexAction() { $format = $this->isMobile() ? 'mob' : 'html'; return $this->render('AcmeBlogBundle:Blog:index.'.$format.'.twig'); }
Но можно ли это сделать глобально? Как сервис или что-то, что выполняется перед каждым запросом, и вносить изменения в правила шаблонов.
Хорошо, поэтому у меня нет полного решения, но немного больше, чем искать один 🙂
Вы можете указать загрузчики (сервисы) для шаблонирования элемента в app / config / config.yml
framework: esi: { enabled: true } #translator: { fallback: %locale% } secret: %secret% router: resource: "%kernel.root_dir%/config/routing.yml" strict_requirements: %kernel.debug% form: true csrf_protection: true validation: { enable_annotations: true } templating: engines: - twig loaders: [moby.loader] default_locale: %locale% trust_proxy_headers: false session: ~
Затем определите упомянутый сервис загрузчика:
services: moby.loader: class: Acme\AppBundle\Twig\Loader\MobyFilesystemLoader arguments: ["@templating.locator", "@service_container"]
После этого определите класс сервиса загрузчика:
namespace Acme\AppBundle\Twig\Loader; use Symfony\Bundle\FrameworkBundle\Templating\Loader\FilesystemLoader; use Symfony\Component\Templating\Storage\FileStorage; class MobyFilesystemLoader extends FilesystemLoader { protected $container; public function __construct($templatePathPatterns, $container) { parent::__construct($templatePathPatterns); $this->container = $container; } public function load(\Symfony\Component\Templating\TemplateReferenceInterface $template) { // Here you can filter what you actually want to change from html // to mob format // ->get('controller') returns the name of a controller // ->get('name') returns the name of the template if($template->get('bundle') == 'AcmeAppBundle') { $request = $this->container->get('request'); $format = $this->isMobile($request) ? 'mob' : 'html'; $template->set('format', $format); } try { $file = $this->locator->locate($template); } catch (\InvalidArgumentException $e) { return false; } return new FileStorage($file); } /** * Implement your check to see if request is made from mobile platform */ private function isMobile($request) { return true; } }
Как вы можете видеть, это не полное решение, но я надеюсь, что это, по крайней мере, указывает на правильное направление.
EDIT: только что выяснили, что есть пакет с возможностями обнаружения мобильных устройств, с настраиваемым движком ветви, который отображает файл шаблона в зависимости от устройства, отправившего запрос ZenstruckMobileBundle , хотя я никогда не использовал его так … 🙂
Ну, вы можете использовать LiipThemeBundle .
Вы можете использовать kernel.view
событий kernel.view
. Это событие приходит в действие, когда контроллер не возвращает ответа, а только данные. Вы можете установить ответ в соответствии с свойством агента пользователя. Например
В вашем контроллере,
public function indexAction() { $data = ... //data prepared for view $data['template_name'] = "AcmeBlogBundle:Blog:index"; return $data; }
И в вашем слушателе событий kernel.view
,
<?php namespace Your\Namespace; use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Templating\EngineInterface; Class ViewListener { /** * @var EngineInterface */ private $templating; public function __construct(EngineInterface $templating) { $this->templating = $templating; } public function onKernelView(GetResponseForControllerResultEvent $event) { $data = $event->getControllerResult(); //result returned by the controller $templateName = $data['template_name']; $format = $this->isMobile() ? 'mob' : 'html'; //isMobile() method may come from a injected service $response = $this->templating->renderResponse($templateName . "." . $format . "twig", $data); $event->setResponse($response); } }
Определение услуги,
your_view_listener.listener: class: FQCN\Of\Listener\Class arguments: [@templating] tags: - { name: kernel.event_listener, event: kernel.view, method: onKernelView }
Вот что сделал трюк для меня в Symfony 2.0:
Переопределите сервис twig.loader, чтобы мы могли установить наш собственный класс:
twig.loader: class: Acme\AppBundle\TwigLoader\MobileFilesystemLoader arguments: locator: "@templating.locator" parser: "@templating.name_parser"
И создайте наш пользовательский класс, который просто устанавливает формат «mob» для шаблонов, если клиент является мобильным устройством:
namespace Acme\AppBundle\TwigLoader; use Symfony\Bundle\TwigBundle\Loader\FilesystemLoader; class MobileFilesystemLoader extends FilesystemLoader { public function findTemplate($template) { if ($this->isMobile()) { $template->set('format', 'mob'); } return parent::findTemplate($template); } private function isMobile() { //do whatever to detect it } }
Я бы предположил, что это не лучше всего обрабатывается контроллером, а средствами CSS-запросов и служит отдельной таблицей стилей для разных классов устройств на основе результатов этого медиа-запроса CSS. Хорошее введение здесь: http://www.adobe.com/devnet/dreamweaver/articles/introducing-media-queries.html
и я бы очень пробовал читать http://www.abookapart.com/products/responsive-web-design . Некоторое мышление было сделано после того, как книга была опубликована, но она заставит вас идти в правильном направлении.
Из моего опыта вы можете, но указав формат в первую очередь – проверьте эти документы , они могут помочь вам
Я думаю, не имеет ничего общего с symfony. Шаблоны предназначены для просмотра. Вы можете достичь этого, используя другой CSS для одного и того же шаблона, чтобы получить разный макет (шаблон). Я использую jQuery и CSS для обработки различных устройств. Вы можете посмотреть на некоторый исходный код пользовательского интерфейса от http://themeforest.net/ ; в частности, этот шаблон . Это одна ручка для другого устройства.
Альтернатива: https://github.com/suncat2000/MobileDetectBundle
Я нашел это довольно хорошим по сравнению с https://github.com/kbond/ZenstruckMobileBundle и https://github.com/liip/LiipThemeBundle