2013-04-30 15 views
10

Tôi đã đọc Twig: render vs include nhưng đó không phải là những gì tôi đang tìm kiếm. Tôi không chắc chắn ở đâu và khi nào tôi nên sử dụng render, và khi nào tôi nên sử dụng bao gồm, vì hành vi của các biểu thức này có vẻ rất giống với tôi.Twig render vs include - Khi nào và ở đâu để sử dụng cái này hay cái kia?

Sự khác nhau cơ bản giữa hai biểu thức này là gì?

+0

Bạn có nghĩa là 'return $ this-> render ('MyBundle :: index.html.twig');' trong bộ điều khiển của bạn và '{% include MyBundle :: index.html.twig%}' trong một bản mẫu? – SirDerpington

+0

@SirDerpington Tôi có nghĩa là '{% render%}' hoặc '{% include%}' cả trong một mẫu cành – 0x1gene

Trả lời

43

Có sự khác biệt lớn giữa {% render %}{% include %}.

  • {% render %} thẻ gọi một hành động: khi bạn làm điều đó, bạn đang thực hiện một bộ điều khiển, tạo ra một bối cảnh mới bên trong bộ điều khiển đó và làm cho một cái nhìn đó sẽ được thêm vào xem hiện tại của bạn.

  • {% include %} thẻ bao gồm tệp cành khác trong tệp hiện tại: không có hành động nào được gọi, vì vậy tệp được bao gồm sẽ sử dụng ngữ cảnh hiện tại của bạn (hoặc ngữ cảnh bạn cung cấp làm tham số) để hiển thị chế độ xem.

Hãy xem chi tiết.


A {% khiến%} Ví dụ

Render là thẻ mà các cuộc gọi một hành động cách rất giống như khi bạn đang gọi đó là sử dụng một tuyến đường, nhưng trong nội bộ, mà không giao dịch HTTP. Cá nhân, tôi đang sử dụng {% render %} khi nội dung được bao gồm trong chế độ xem của tôi cần được làm mới bằng ajax. Theo cách đó, tôi có thể gọi cùng một hành động bằng cách sử dụng định tuyến chuẩn khi có tương tác bên trong trang của tôi.

Xem xét một trang đơn giản có biểu mẫu ajax giúp bạn thêm nội dung và bảng nội dung được làm mới động.

enter image description here

Thực thể Stuff

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

} 

Dạng Stuff

<?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"; 
    } 

} 

File 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 } 

Các bộ điều khiển

<?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); 
    } 

Các 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> 

Các 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 %} 

này sẽ cung cấp cho bạn một số hình thức xấu xí nhìn như thế này :

enter image description here

Vấn đề là: nếu bạn làm mới trang của mình hoặc nếu bạn thêm/xóa nội dung, bộ điều khiển tương tự sẽ được gọi.Không cần phải tạo một số logic phức tạp hoặc mã trùng lặp.


Một {% bao gồm%} Ví dụ

Thẻ [% include %} phép bạn bao gồm một số đoạn mã cành lá về cách thức tương tự như hướng dẫn include làm việc trong PHP. Điều này có nghĩa là về cơ bản: {% include %} cung cấp cho bạn cách để sử dụng lại một số mã chung ở khắp mọi nơi trong ứng dụng của bạn.

enter image description here

Chúng tôi ở lại với ví dụ chất liệu của chúng tôi: giữ StuffEntity và StuffData nhưng thay thế sau:

Routing:

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 } 

Bộ xử lý:

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

Như bạn có thể thấy ở đây, chỉ có một điều khiển mà khởi tạo các yếu tố toàn bộ trang (hình thức và bảng), do đó không thể làm giao dịch không đồng bộ . Tuy nhiên, bạn có thể bao gồm tệp genericTable.html.twig này ở bất kỳ đâu trong ứng dụng của bạn.


Kết luận

Bạn sẽ sử dụng {% render %} khi xem để chèn có thể được làm mới bằng một con đường tiêu chuẩn hoặc khi quan điểm chèn là hoàn toàn độc lập từ bối cảnh hiện nay.

Bạn sẽ sử dụng {% include %} khi bạn cần sử dụng một đoạn mã vài lần trong ứng dụng của mình, nhưng bạn cần phải khởi tạo ngữ cảnh bắt buộc của chế độ xem trong cùng hành động với tệp gốc của tệp gốc.

+0

Cảm ơn tôi đã không nghĩ về Ajax, câu trả lời của bạn phù hợp với nhu cầu của tôi! – 0x1gene

+0

Tôi không biết về thẻ '{% render%}' trong twig. Bạn có thể chỉ cho tôi một mục nhập docu hoặc một số mẫu không? Nó có vẻ thực sự thú vị – SirDerpington

+0

Hmm, có vẻ như không được ghi lại nhiều, có một cái nhìn về [Symfony2 doc] cũ (http://symfony.com/doc/2.0/book/templating.html), và tìm kiếm 'Bộ điều khiển nhúng '. –

Các vấn đề liên quan