私はまだSymfonyとTwigをかなり新しくしています。テンプレートに再利用可能なコードのスニペットを含める/作成する方法を知りました。たとえば、すべてのページに表示するサイドバーがあるとします。symfony(Twig)に再利用可能なウィジェットを含めるには?
{% extends 'AppBundle::base.html.twig' %}
{% block body %}
<div id="wrapper">
<div id="content-container">
{# Main content... #}
</div>
<div id="sidebar">
{% include 'sidebar.html.twig' %}
</div>
</div>
{% endblock %}
サイドバーには、すべて独自のロジックを実行するウィジェットが2つあります。それらのウィジェットの作成/含める方法は?
これまでのところ、私はいくつかの解決策を見つけました。
コントローラ
は、最初は小枝にembed the widget as a controller(s)であったように。
class WidgetController extends Controller
{
public function recentArticlesWidgetAction()
{
// some logic to generate to required widget data
// ...
// Render custom widget template with data
return $this->render('widgets/recentArticles.html.twig', array('data' => $data)
);
}
public function subscribeButtonWidgetAction()
{
// ...
return $this->render('widgets/subscribeButton.html.twig', array('data' => $data)
}
// Many more widgets
// ...
}
とサービス
よう
<div id="sidebar">
{# Recent Articles widget #}
{{ render(controller('AppBundle:Widget:recentArticlesWidget')) }}
{# Subscribe-Button widget #}
{{ render(controller('AppBundle:Widget:subscribeButtonWidget')) }}
{# and so on #}
</div>
LIKE「sidebar.html.twig」に私も何人かの人々がそれを使用することができます(サービスとしてのウィジェットを登録見てきたことなどがTwigで直接)。ウィジェットメインクラス、サービスとして登録されている
// src/AppBundle/Service/RecentArticlesWidget.php
namespace AppBundle\Service;
use Symfony\Component\DependencyInjection\ContainerInterface;
class RecentArticlesWidget
{
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function getRecentArticles()
{
// do some logic (use container for doctrine etc.)
}
}
、コントローラにテンプレートに渡さ
# src/AppBundle/Resources/config/services.yml
services:
recentArticlesWidget:
class: AppBundle\Service\RecentArticlesWidget
arguments: ["@service_container"]
と、
namespace AppBundle\Controller;
class SidebarController {
public function showAction($request) {
// Get the widget(s)
$recentArticlesWidget = $this->get('recentArticlesWidget');
// Pass it (them) along
return $this->render('sidebar.html.twig', array('recentArticlesWidget' => $recentArticlesWidget));
}
}
は、それが単にこのように使用することができますTwigで
{# sidebar.html.twig #}
{{ recentArticlesWidget.getRecentArticles()|raw }}
の場合は、サービスをTwigグローバル変数に直接追加することもできます。この方法では、コントローラーの視界に入る必要はありません。小枝拡張
として
#app/config/config.yml
twig:
globals:
# twig_var_name: symfony_service
recentArticlesWidget: "@recentArticlesWidget"
この1つは、上記サービス(see the documentation)を使用することに非常に類似しています。あなたは付加されたタグを持つサービスとして
# src/AppBundle/Resources/config/services.yml
services:
recentArticlesWidget:
class: AppBundle\Twig\RecentArticlesWidgetExtension
arguments: [@service_container]
tags:
- { name: twig.extension }
と単純には小枝
にグローバル関数のようにそれを使用することを// src/AppBundle/Twig/RecentArticlesWidgetExtension.php
namespace AppBundle\Twig;
class RecentArticlesWidgetExtension extends \Twig_Extension
{
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function getFunctions()
{
return array(
"getRecentArticles" => new Twig_Function_Method($this, "getRecentArticles")
// register more functions
);
}
public function getRecentArticles()
{
// do some logic (use container for doctrine etc.)
}
// Some more functions...
public function getName()
{
return 'WidgetExtension';
}
}
登録以前に示したサービスとほぼ同じです小枝拡張クラスを作成します私が気づい
{# sidebar.html.twig #}
{{ getRecentArticles() }}
思考
ことの一つは、最後の2メートルとのことです論理と見解はもはや分離されていないように見えるということです。あなたは基本的にウィジェット関数を書いて、その関数にウィジェットの完全なhtmlを出力させます。これはSymfonyが実行しようとするモジュール性とパターンに反しているようです。
一方、1つのウィジェットごとに個別のコントローラまたはコントローラアクション(独自のtwigレンダー)を呼び出すと、必要以上に処理が必要になるようです。私はそれが実際に何かを遅くするかどうかはわかりませんが、私はそれが過剰かどうか疑問に思います。
短い話ですが、再利用可能なウィジェットをSymfonyで使用するためのベストプラクティスはありますか?これらのメソッドのいくつかは混在する可能性があるので、私はこれについて最善を尽くす方法を考えていただけです。
ありがとうございました!あなたが提案するものは有用で正しいものです。しかし、私の質問は、小枝テンプレートのサイドバー(または他の場所)に複雑なコードをどのように置くのが良いかということに沿ったものでした。同様に、独自のクエリを実行する必要があり、すべての種類のロジックを持ち、出力を生成します。メインコントローラーでは通常通り過ぎることのないもの。私は簡単な例としてウィジェットを取った(私に最も人気のある3つの記事を取り出し、うまく表示する)。私は個人的に上記のように追加の「ウィジェットコントローラ」を埋め込む傾向がありますが、他の人たちが何をしたのか不思議でした。 – Mvin