4

ユースケース
Symfony2 上で CMF を開発しています。機能の 1 つは「ウィジェット」のサポートです。これは、エンド ユーザーが小さな「ブロック」または「モジュール」をページに追加できるようにする機能です。例:

  • 小さなログインフォーム
  • 製品一覧
  • ギャラリーからのいくつかの写真
  • ショッピングカート

これらのウィジェットのほとんどは、通常のフルページのルート/コントローラーにリンクするという考えです。

例: ユーザーは、コンテンツ ページのサイドバーに人気のある製品のリストを表示したいと考えています。アイテムは、ProductController の通常の /product/{name} ルートにリンクします。ただし、この場合のリストはウィジェットになります。エンド ユーザーは、どこに配置する必要があるか、たとえば、どれだけのアイテムを表示する必要があるかを定義できます。

「ウィジェット」の動作は、通常の Symfony2 コントローラーと同じで、ルート、アクション、ビューのレンダリングなどがあります。ウィジェットをロードし、構成し、適切な場所にレンダリングするためのキャッチオール ルートを持つ WidgetManager があります。

私は Symfony2 の経験はあまりありませんが、今では 3 か月以上使っています。私は間違いなく Symfony2 を使い続けたいと思っていますが、私のアイデアのいくつかを実現するには魔法を追加する必要があります。

質問
1 つの要求で複数のコントローラー (ウィジェット) のレンダリングをサポートする最善の方法は何ですか?

Research
Symfony の TwigExtension "ActionExtension" には、基本的な考え方を含む "render" メソッドが含まれています。

<div id="sidebar">
    {% render "AcmeArticleBundle:Article:recentArticles" with {'max': 3} %}
</div>

(ドキュメント: http://symfony.com/doc/current/book/templating.html#embedding-controllers )

しかし、それはかなり限られています。このアプローチにはいくつかの問題があります。

  • 「ウィジェット」をレンダリングする前に構成できません (例: $myWidget->set('show_toolbar', false))。すべてのオプションをコントローラー アクション パラメーターとして渡したくありません。
  • テンプレートの継承を使用することはできません。<HEAD>たとえば、de baseブロックにアセット参照 (javascript/css) を「注入」するためにこれが必要です。

私が欲しいもの

次のコードが機能するようにします (これは単純化された例です)。

// Serius\PageBundle\Controller\PageController.php

// executed by a catch-all route
public function indexAction($url) {
    // load CMS page, etc
    
    $widgets = $this->loadWidgets($page); // widgets configuration is stored in database
    // at this point, $widgets is an array of Controller *instances*
    // meaning, they are already constructed and configured

    return $this->render("SeriusPageBundle:Page:content.html.twig", array(
        'widgets' => $widgets
    ));   
}

Serius\PageBundle\Resources\views\Page\content.html.twig

{% extends 'SeriusPageBundle::layout.html.twig' %}

{% block content %}
    {% for widget in widgets %}
    <div>
        {% render widget %}
        <!-- Of course, this doesn't work, I would have to create my own Twig extension -->
    </div>
    {% endfor %}
{% endblock %}

ウィジェット テンプレートの例:

{% extends '::base.html.twig' %}
{% block stylesheets %}
  My stylesheets
{% endblock %}

{% block body %}
    This is a shoppingcart widget!
{% endblock %}

どうすればこれを達成できますか?誰かがこのような経験をしていますか?私はすでに Symfony CMF プロジェクトを見てきましたが、これをサポートしていません (私が知る限り)。

4

2 に答える 2

1

似たようなことが起こっており、このコードが役立つと思います。選択したテンプレートでは、ブロックの名前を持つ変数を取得します。

public function render()
{       
    $modules = $this->moduleService->getModules();

    foreach($modules as $m){
        $templateName = $m->getTemplateName();

        $template = $this->twig->loadTemplate($templateName);
        $blockNames = $template->getBlockNames();

        foreach($blockNames as $b){
            if(isset($this->blocks[$b]) == false)
                $this->blocks[$b] = '';
            $this->blocks[$b] .= $template->renderBlock($b, array('a' => 'aaa', 'b' => 'bbb'));
        }

    }
    $content = $this->twig->render('Admin/index.html.twig',$this->blocks);
    return new \Symfony\Component\HttpFoundation\Response($content);
}
于 2012-09-09T10:28:58.753 に答える