それは可能ですか(そしてどのように)
Idがやりたいのは、コントローラーを変更せずにさまざまなテンプレートをロードすることです。
[〜#〜] update [〜#〜]
ここでの本当の問題は検出部分ではなく、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;
}
}
ご覧のとおり、これは完全な解決策ではありませんが、少なくとも、これが正しい方向を示していることを願っています。
編集:リクエストを送信したデバイスに応じてテンプレートファイルをレンダリングするカスタムtwigエンジンを備えたモバイル検出機能を備えたバンドルがあることがわかりました ZenstruckMobileBundle 、私は使用したことがないので... :)
さて、あなたは LiipThemeBundle を使うことができます。
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 }
これがSymfony2.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とは何の関係もないと思います。テンプレートはVIEW用です。これは、同じテンプレートに異なるCSSを使用して、異なるレイアウト(テンプレート)を取得することで実現できます。私はjQueryとCSSを使用してさまざまなデバイスを処理しています。 UIのソースコードを http://themeforest.net/ ;から確認することをお勧めします。具体的にはこれ テンプレート 。これは別のデバイスを処理するものです。
私の経験から、あなたはできますが、最初にフォーマットを指定することによって-これらをチェックしてください docs 、彼らはあなたを助けることができるかもしれません