2012-01-05 8 views
1

OKパス設定を動的に、私は私のtestpageは小枝Symfony2の-ルーキー:

<li> 
<a href="{{ path("main", {"_locale": "en","name": name}) }}"> 
<img src="{{ asset('img/flags/gb.png') }}"></a></li> 
<li> 
<a href="{{ path("main", {"_locale": "de","name": name}) }}"> 
<img src="{{ asset('img/flags/de.png') }}"></a></li> 

にこのようJMSTranslationBundleとの組み合わせで言語を切り替えるためのコードを置くことに成功したが、これは私がどのようにpath ("main") のためにできる働くことになります必要なパラメータ(この場合は"name": name?)を含む現在作業中のページ/ルートに対して動的に動作させるようにします。私が現在「私たちについて」の英語ページにある場合、私は自動的に私たちについてのドイツのページに切り替えることができますそのパラメータは?それは可能ですか?パスごとに各小枝ページ/テンプレートをハードコードする必要がありますか?

答えて

3

ハードコーディングは良い考えではありませんが、これは達成可能ですが、私が知っている限り、箱から出ることはできません。私が同じパスとparamsを持つURLを別のロケールに提供するために行ったのは、それを行うためのカスタムtwig拡張を作成することでした。

この拡張機能は、現在のルート、現在のパラメータを読み取ってプライベートパラメータを削除し、別のロケールに対して同じルートを生成する新しい分岐機能を提供します。ここで問題になっている小枝拡張子:

<?php 

namespace Acme\WebsiteBundle\Twig\Extension; 

use Symfony\Component\DependencyInjection\ContainerInterface; 

class LocalizeRouteExtension extends \Twig_Extension 
{ 
    protected $request; 
    protected $router; 

    public function __construct(ContainerInterface $container) 
    { 
     $this->request = $container->get('request'); 
     $this->router = $container->get('router'); 
    } 

    public function getFunctions() 
    { 
     return array(
      'localize_route' => new \Twig_Function_Method($this, 'executeLocalizeRoute', array()), 
     ); 
    } 

    public function getName() 
    { 
     return 'localize_route_extension'; 
    } 

    /** 
    * Execute the localize_route twig function. The function will return 
    * a localized route of the current uri retrieved from the request object. 
    * 
    * The function will replace the current locale in the route with the 
    * locale provided by the user via the twig function. 
    * 
    * Current uri: http://www.example.com/ru/current/path?with=query 
    * 
    * In Twig: {{ localize_route('en') }} => http://www.example.com/en/current/path?with=query 
    *   {{ localize_route('fr') }} => http://www.example.com/fr/current/path?with=query 
    * 
    * @param mixed $parameters The parameters of the function 
    * @param string $name The name of the templating to render if needed 
    * 
    * @return Output a string representation of the current localized route 
    */ 
    public function executeLocalizeRoute($parameters = array(), $name = null) 
    { 
     $attributes = $this->request->attributes->all(); 
     $query = $this->request->query->all(); 
     $route = $attributes['_route']; 

     # This will add query parameters to attributes and filter out attributes starting with _ 
     $attributes = array_merge($query, $this->filterPrivateKeys($attributes)); 

     $attributes['_locale'] = $parameters !== null ? $parameters : \Locale::getDefault(); 

     return $this->router->generate($route, $attributes); 
    } 

    /** 
    * This function will filter private keys from the attributes array. A 
    * private key is a key starting with an underscore (_). The filtered array is 
    * then returned. 
    * 
    * @param array $attributes The original attributes to filter out 
    * @return array The filtered array, the array withtout private keys 
    */ 
    private function filterPrivateKeys($attributes) 
    { 
     $filteredAttributes = array(); 
     foreach ($attributes as $key => $value) { 
      if (!empty($key) && $key[0] != '_') { 
       $filteredAttributes[$key] = $value; 
      } 
     } 

     return $filteredAttributes; 
    } 
} 

、あなたのバンドルを介して、または直接app/config下に配置config.ymlファイルのどちらかにこのサービス定義をロードすることによって、この小枝の拡張機能を有効にすることができます。

services: 
     acme.twig.extension: 
     class: Acme\WebsiteBundle\Twig\Extension\LocalizeRouteExtension 
     scope: request 
     arguments: 
      request: "@request" 
      router: "@router" 
     tags: 
      - { name: twig.extension } 

そして今、あなたは、現在ロードされたページの異なるバージョンを提案する小枝でこれを行うことができます。

<a id='englishLinkId' href="{{ localize_route('en') }}"> 
    English 
</a> 
<a id='frenchLinkId' href="{{ localize_route('fr') }}"> 
    Français 
</a> 

は、このことができますし、それはあなたが探しているものであると思います。

編集:

直接小枝延長の範囲を狭めることはできないようです。これを避けるには、依存関係コンテナをすべて注入してから、必要なサービスを取得します。これは、twig拡張のコンストラクタ定義と拡張のサービス定義を変更することによって反映されるべきです。以前の答えを編集し、新しい更新コンストラクタ定義と新しいサービス定義を確認しました。

もう1つの解決策は、ルートのローカライズを担当するヘルパーサービスを注入することです。このヘルパーサービスは要求スコープ内にある必要があります。実際、これは私が自分のコードで持っているものです。私はRoutingHelperサービスをtwigの拡張機能に注入しました。その後、方法executeLocalizeRouteでは、私はハードワークをするために私のヘルパーを使用します。

すべてが動作しているかどうかを教えてください。

よろしく、
マット

+0

甘い...本当にきれいに見えます。ありがとうございました。パラメターを認識したら、私にとって重要です。もっと簡単な選択肢は、各ユーザーが設定でロケールを定義し、自動的にそこから設定します....しかし、私は少なくともログインすることなくこのページを必要とします。 – Confidence

+0

私はあなたの解決策を試みました。しかし、私は次のようになります: 'Scope Widening Injection detected:定義 "twig"は狭い範囲に属するサービス "tracker.twig.extension"を参照します。一般的には、 "twig"をスコープ "request"に移動するか、コンテナ自体を注入し、必要になるたびにサービス "tracker.twig.extension"を要求することによってプロバイダパターンに依存する方が安全です。しかし、まれにしか必要ではないかもしれない特別なケースでは、strict = falseへの参照を設定して をこのエラーから取り除くことができます。 – Confidence

+0

問題を解決するために私の答えを編集します。 – Matt