2013-04-30 16 views
10

我讀過Twig: render vs include,但這不是我要找的。我不知道應該在何時何地使用渲染,何時應該使用include,因爲這些表達式的行爲看起來與我非常相似。枝條渲染與包含 - 何時何地使用其中一種?

這兩個表達式之間的根本區別是什麼?

+0

您的意思是在您的控制器中返回$ this-> render('MyBundle :: index.html.twig');'在您的控制器中使用'{%include MyBundle :: index.html.twig%}'模板? – SirDerpington 2013-04-30 11:27:41

+0

@SirDerpington我的意思是'{%render%}'或'{%include%}'都在一個樹枝模板中 – 0x1gene 2013-04-30 12:03:02

回答

43

{% render %}{% include %}之間有很大的不同。

  • {% render %}標籤調用一個動作:當你這樣做,你正在執行一個控制器,創建控制器內一個新的上下文並呈現將被添加到您當前視圖的視圖。

  • {% include %}標籤包含當前另一個樹枝文件:沒有任何操作被調用,因此包含的文件將使用您當前的上下文(或您提供的上下文作爲參數)來呈現視圖。

讓我們來看看細節。


A {%渲染%}例如

渲染是調用一個動作,如果你是使用路由調用它完全相同的方式,但在內部,沒有HTTP事務的標籤。就我個人而言,我使用{% render %}當我的視圖中包含的內容需要使用ajax刷新。這樣,當我的頁面發生交互時,我可以使用標準路由來調用相同的操作。

考慮一個帶有ajax表單的簡單頁面,它可以幫助您添加東西以及動態刷新東西表格。

enter image description here

東西實體

<?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 %} 

這會給你一些醜陋的形式看起來像這樣:

enter image description here

問題是:如果刷新頁面或者添加/刪除東西,則會調用相同的控制器。無需創建一些複雜的邏輯或複製代碼。


的{%包括%}例如

[% include %}標籤讓你包括有關以同樣的方式有些一段樹枝代碼爲include指令在PHP的作品。這意味着基本上:{% include %}爲您提供了一種在應用程序的任何地方重用某些通用代碼段的方法。

enter image description here

我們留在我們的東西例如:保持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 %} 

正如你可以在這裏看到,只有一個控制器初始化頁面(表格和表格)的所有元素,所以這是不可能做異步事務。但是,您可以在應用程序的任何位置包含這個genericTable.html.twig文件。


結論

將使用{% render %}時可使用標準路由或何時插入視圖是從當前上下文完全獨立的刷新以插入視圖。

當您需要在您的應用程序中多次使用一段枝代碼時,您將使用{% include %},但您需要在與父枝文件相同的操作中初始化包含視圖的必需上下文。

+0

謝謝我沒有想過Ajax,你的answear很適合我的需求! – 0x1gene 2013-04-30 12:06:07

+0

我不知道枝條中的{%render%}標籤。你能指給我一個文件記錄或一些樣本嗎?它看起來很有趣 – SirDerpington 2013-04-30 12:27:10

+0

嗯,它看起來沒有很多記錄,看看老[Symfony2文檔](http://symfony.com/doc/2.0/book/templating.html),並搜索「嵌入控制器'。 – 2013-04-30 12:55:35