Twig: render vs includeを読みましたが、探しているものではありません。これらの式の動作は私と非常に似ているように見えるため、いつどこで render を使用する必要があるのか 、いつ include を使用する必要があるのか わかりません。
これら 2 つの式の根本的な違いは何ですか?
Twig: render vs includeを読みましたが、探しているものではありません。これらの式の動作は私と非常に似ているように見えるため、いつどこで render を使用する必要があるのか 、いつ include を使用する必要があるのか わかりません。
これら 2 つの式の根本的な違いは何ですか?
と の間には大きな違いが{% render %}
あり{% include %}
ます。
{% render %}
タグはアクションを呼び出します。これを行うと、コントローラーが実行され、そのコントローラー内に新しいコンテキストが作成され、現在のビューに追加されるビューがレンダリングされます。
{% include %}
タグには、現在のファイルに別の小枝ファイルが含まれています。アクションが呼び出されないため、含まれているファイルは現在のコンテキスト (またはパラメーターとして指定したコンテキスト) を使用してビューをレンダリングします。
詳しく見てみましょう。
Render は、ルートを使用してアクションを呼び出す場合とまったく同じ方法でアクションを呼び出すタグですが、内部的には HTTP トランザクションを使用しません。個人的には{% render %}
、ビューに含まれるコンテンツを ajax を使用して更新する必要がある場合に使用しています。このようにして、ページ内でインタラクションが発生したときに、標準ルーティングを使用して同じアクションを呼び出すことができます。
スタッフの追加に役立つ ajax フォームと、動的に更新されるスタッフのテーブルを備えた単純なページを考えてみましょう。
スタッフエンティティ
<?php
// src/Fuz/HomeBundle/Entity/StuffData.php
namespace Fuz\HomeBundle\Entity;
class StuffData
{
private $stuff;
public function getStuff()
{
return $this->stuff;
}
public function setStuff($stuff)
{
$this->stuff = $stuff;
return $this;
}
}
スタッフフォーム
<?php
// src/Fuz/HomeBundle/Form/StuffType.php
namespace Fuz\HomeBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class StuffType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('stuff', 'text', array('label' => ''));
}
public function getDefaultOptions(array $options)
{
return array (
'data_class' => 'Fuz\HomeBundle\Entity\StuffData',
);
}
public function getName()
{
return "Stuff";
}
}
routing.yml ファイル
# src/Fuz/HomeBundle/Resources/config/routing.yml
fuz_home:
pattern: /
defaults: { _controller: FuzHomeBundle:Default:index }
fuz_add_stuff:
pattern: /add_stuff
defaults: { _controller: FuzHomeBundle:Default:addStuff }
fuz_del_stuff:
pattern: /del_stuff
defaults: { _controller: FuzHomeBundle:Default:delStuff }
fuz_list_stuffs:
pattern: /list_stuffs
defaults: { _controller: FuzHomeBundle:Default:listStuffs }
コントローラー
<?php
namespace Fuz\HomeBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Fuz\HomeBundle\Entity\StuffData;
use Fuz\HomeBundle\Form\StuffType;
class DefaultController extends Controller
{
/**
* Route : fuz_home
*/
public function indexAction()
{
// Initialize some stuffs, stored in the session instead of in a table for simplicity
if (!$this->get('session')->has('stuffs'))
{
$this->get('session')->set('stuffs', array());
}
// Create the form used to add a stuff
$form = $this->createForm(new StuffType(), new StuffData());
$twigVars = array(
'formAddStuff' => $form->createView(),
);
return $this->render('FuzHomeBundle:Default:index.html.twig', $twigVars);
}
/**
* Route : fuz_add_stuff
*/
public function addStuffAction()
{
$data = new StuffData();
$form = $this->createForm(new StuffType(), $data);
$form->bindRequest($this->getRequest());
if ($form->isValid())
{
$stuffs = $this->get('session')->get('stuffs');
$stuffs[] = $data->getStuff();
$this->get('session')->set('stuffs', $stuffs);
}
return $this->forward("FuzHomeBundle:Default:listStuffs");
}
/**
* Route : fuz_del_stuff
*/
public function delStuffAction()
{
$stuffId = $this->getRequest()->get('stuffId');
$stuffs = $this->get('session')->get('stuffs');
if (array_key_exists($stuffId, $stuffs))
{
unset($stuffs[$stuffId]);
$this->get('session')->set('stuffs', array_values($stuffs));
}
return $this->forward("FuzHomeBundle:Default:listStuffs");
}
/**
* Route : fuz_list_stuffs
*/
public function listStuffsAction()
{
$stuffs = $this->get('session')->get('stuffs');
$twigVars = array(
'stuffs' => $stuffs,
);
return $this->render('FuzHomeBundle:Default:listStuffs.html.twig', $twigVars);
}
index.html.twig
{# src/Fuz/HomeBundle/Resources/views/Default/index.html.twig #}
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
{# The form that will be posted asynchronously #}
<form id="formStuff">
{{ form_widget(formAddStuff) }}
<input type="button" id="add-stuff" value="Add stuff" />
</form>
<br/><br/>
{# The div that will contain the dynamic table #}
<div id="list-stuffs">
{% render path('fuz_list_stuffs') %}
</div>
{# When a click is made on the add-stuff button, we post the form #}
<script type="text/javascript">
$('#add-stuff').click(function() {
$.post('{{ path('fuz_add_stuff') }}', $('#formStuff').serialize(), function(data) {
$('#list-stuffs').html(data);
});
});
</script>
listStuffs.html.twig
{# listStuf
fs.html.twig #}
{% if stuffs | length == 0 %}
No stuff to display !
{% else %}
<table style="width: 50%">
{% for stuffId, stuff in stuffs %}
<tr>
<td>{{ stuff }}</td>
<td><a data-stuff-id="{{ stuffId }}" class="delete-stuff">Delete</a></td>
</tr>
{% endfor %}
</table>
<script type="text/javascript">
$('.delete-stuff').click(function() {
$.post('{{ path('fuz_del_stuff') }}', {'stuffId': $(this).data('stuff-id')}, function(data) {
$('#list-stuffs').html(data);
});
});
</script>
{% endif %}
これにより、次のような醜いフォームが得られます。
ポイントは、ページを更新したり、コンテンツを追加/削除したりすると、同じコントローラーが呼び出されることです。複雑なロジックを作成したり、コードを複製したりする必要はありません。
このタグを使用すると、PHP で命令が機能する[% include %}
のとほぼ同じ方法で、いくつかの twig コードを含めることができます。include
これは基本的に、アプリケーションのあらゆる場所で一般的なコード{% include %}
を再利用する方法を提供することを意味します。
スタッフの例にとどまります: StuffEntity と StuffData を保持しますが、以下を置き換えます。
ルーティング :
fuz_home:
pattern: /
defaults: { _controller: FuzHomeBundle:Default:index }
fuz_add_stuff:
pattern: /add_stuff
defaults: { _controller: FuzHomeBundle:Default:addStuff }
fuz_del_stuff:
pattern: /del_stuff
defaults: { _controller: FuzHomeBundle:Default:delStuff }
コントローラー:
public function indexAction()
{
// Initialize some stuffs, stored in the session instead of in a table for simplicity
if (!$this->get('session')->has('stuffs'))
{
$this->get('session')->set('stuffs', array());
}
// Create the form used to add a stuff
$form = $this->createForm(new StuffType(), new StuffData());
$stuffs = $this->get('session')->get('stuffs');
$twigVars = array(
'formAddStuff' => $form->createView(),
'stuffs' => $stuffs,
);
return $this->render('FuzHomeBundle:Default:index.html.twig', $twigVars);
}
/**
* Route : fuz_add_stuff
*/
public function addStuffAction()
{
$data = new StuffData();
$form = $this->createForm(new StuffType(), $data);
$form->bindRequest($this->getRequest());
if ($form->isValid())
{
$stuffs = $this->get('session')->get('stuffs');
$stuffs[] = $data->getStuff();
$this->get('session')->set('stuffs', $stuffs);
}
return $this->forward("FuzHomeBundle:Default:index");
}
/**
* Route : fuz_del_stuff
*/
public function delStuffAction()
{
$stuffId = $this->getRequest()->get('id');
$stuffs = $this->get('session')->get('stuffs');
if (array_key_exists($stuffId, $stuffs))
{
unset($stuffs[$stuffId]);
$this->get('session')->set('stuffs', array_values($stuffs));
}
return $this->forward("FuzHomeBundle:Default:index");
}
index.html.twig :
{# src/Fuz/HomeBundle/Resources/views/Default/index.html.twig #}
<form action="{{ path('fuz_add_stuff') }}" method="post">
{{ form_widget(formAddStuff) }}
<input type="submit" value="Add stuff" />
</form>
<br/><br/>
{# Here we include our "generic" table with the stuff table as parameter #}
{%
include 'FuzHomeBundle:Default:genericTable.html.twig'
with {
'route': 'fuz_del_stuff',
'data' : stuffs,
}
%}
genericTable :
{# src/Fuz/HomeBundle/Resources/views/Default/genericTable.html.twig #}
{% if data | length == 0 %}
No data to display !
{% else %}
<table style="width: 50%">
{% for id, elem in data %}
<tr>
<td>{{ elem }}</td>
<td><a href="{{ path(route, {'id': id}) }}">Delete</a></td>
</tr>
{% endfor %}
</table>
{% endif %}
ここでわかるように、ページの要素全体 (フォームとテーブル) を初期化するコントローラーは 1 つしかないため、非同期トランザクションを実行することはできません。ただし、この genericTable.html.twig ファイルをアプリケーションのどこにでも含めることができます。
挿入するビューが標準ルートを使用{% render %}
して更新される可能性がある場合、または挿入するビューが現在のコンテキストから完全に独立している場合に使用します。
{% include %}
アプリケーションで twig コードを数回使用する必要がある場合に使用しますが、親の twig ファイルと同じアクションで、含まれるビューの必要なコンテキストを初期化する必要があります。