8

Symfony2プロジェクトでさまざまなコンテキストでさまざまなビューをレンダリングしたいと思います。同じアクションに複数のルートを使用していますが、同じコントローラーで別のページ(ビュー)をレンダリングしたいと思います。たとえば、私は持っています:

@Route("/articles/show", name="articles_show")
@Route("/mobile/articles/show", name="mobile_articles_show")

どちらのルート同じアクションArticlesController:showAction()を使用していますが、2つの異なるテンプレート(モバイルユーザーと通常のテンプレート)をレンダリングする必要があります。

show.html.twig
mobile.show.html.twig

コントローラーでifステートメントなどを使用したくないので、リスナーを作成しました(preExecute関数と同様)

これが私のリスナーを定義する部分または私のconfig.ymlです

services:
    controller.pre_execute_listener:
        class: MyProject\MyBundle\Listener\ControllerListener
        arguments: ["@security.context", "@doctrine", "@router", "@session"]
        tags:- { name: kernel.event_listener, event: kernel.controller, method: preExecute }

私はリスナーのpreExecute関数でそのようなことをすることを考えていました:

if(substr($route,0,7) == 'mobile_'){
    $view = 'mobile.'.$view;
}

残念ながら、レンダリングされる直前に、$viewを取得したりビューを「オンザフライ」で更新したりする方法を見つけることができません。

私の質問が十分に明確であることを願っています、事前に感謝します、どんなアイデアでも大歓迎です:)

J。

4

4 に答える 4

13

解決策は次のとおりです。

まず、kernel.controllerではなく、kernel.view をリッスンする必要があります。

次に、" @templating " サービスを使用します (ヒントをくれた Marko Jovanovic に感謝します)。

だからここに私の新しいconfig.ymlがあります:

services:
    controller.pre_execute_listener:
        class: MyProject\MyBundle\Listener\ControllerListener
        arguments: ["@templating"]
        tags:
                - { name: kernel.event_listener, event: kernel.view, method: preExecute }

最後に、リスナーのpreExecute 関数を次に示します。

public function preExecute(\Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent $event){
    //result returned by the controller
    $data = $event->getControllerResult();

    /* @var $request  \Symfony\Component\HttpFoundation\Request */
    $request =  $event->getRequest();       
    $template = $request->get('_template');
    $route = $request->get('_route');

    if(substr($route,0,7) == 'mobile_'){
        $newTemplate = str_replace('html.twig','mobile.html.twig',$template);

        //Overwrite original template with the mobile one
        $response = $this->templating->renderResponse($newTemplate, $data);
        $event->setResponse($response);
    }
}

お役に立てれば!

J.

于 2012-09-13T09:26:45.720 に答える
4

注目に値する: 受け入れられた解決策は、Response-object を直接返す場合 (たとえば、 を呼び出す場合) には実際には機能しません。その場合、イベントは発生しない$this->render()ためです。kernel.view

コントローラが Response オブジェクトを返さない場合、カーネルは別のイベントを送出します - kernel.view.

Symfony の HTTP カーネル ドキュメントを参照してください。

これを回避する方法は見つかりませんでしたが、同じ問題に対する別の興味深い解決策を見つけました。ZenstruckMobileBundle のように twig のレンダリング エンジンを拡張するか、LiipThemeBundleのような独自のファイル ロケーターを作成するだけです

[編集:] あるいは、 をオーバーライドすることもできますTemplateNameParser

于 2014-09-24T13:11:39.410 に答える
1

controller.pre_execute_listener の引数として「@templating」サービスを追加できます。

于 2012-08-20T08:15:44.237 に答える
0

デバイスの検出はルートに到達する前に行われているようです。したがって、リクエスト前の検出のおかげで、モバイルユーザーがモバイルルートを使用することを期待していると思います。これは、すべてのテンプレートとURL生成で処理するのが難しいようです。

( Categorizrまたはいくつかの素晴らしいapache構成のおかげで)前または後でデバイスを検出する方が良いかもしれませんが、モバイル検出に使用されるルートに依存しません。

Categorizrと、テンプレートレンダリングを呼び出すその方法との統合は素晴らしいかもしれません。

次に、適切なテンプレート/テーマを使用するための優れたバンドルを使用するか、より一般的な機能を提供するバンドルを使用します

于 2012-09-13T15:50:47.983 に答える