2013-04-30 7 views
10

Przeczytałem Twig: render vs include, ale to nie jest to, czego szukam. Nie jestem pewien, gdzie i kiedy powinienem użyć renderowania, a kiedy powinienem użyć include, ponieważ zachowanie tych wyrażeń wydaje mi się bardzo podobne.Twig render vs include - Kiedy i gdzie użyć jednego lub drugiego?

Jakie są podstawowe różnice między tymi dwoma wyrażeniami?

+0

Czy oznacza to, że 'return $ this-> render ('MyBundle :: index.html.twig');' w kontrolerze i '{% obejmują MyBundle :: index.html.twig%}' w sposób szablon? – SirDerpington

+0

@SirDerpington I Mean '{% renderowanie%}' lub '{% include%}' zarówno w szablonie gałązka – 0x1gene

Odpowiedz

43

Istnieją znaczne różnice między {% render %} i {% include %}.

  • {% render %} tag wywołuje działania: kiedy to robisz, jesteś wykonywania kontrolera, tworząc nowy kontekst wewnątrz tego kontrolera i świadczy, że zostanie dodana do bieżącego widoku.

  • {% include %} tag zawiera inny plik w bieżącym gałązka jeden: nie ma działania nazywa, więc dołączony plik użyje aktualny kontekst (lub kontekst dajesz jako parametr) do renderowania widoku.

Zobaczmy to szczegółowo.


odpowiedzi {%}% renderowanie przykład

Render jest tag, który nazywa to działanie bardzo tak samo jakbyś wzywającą go za pomocą trasy, ale wewnętrznie, bez transakcji HTTP. Osobiście używam {% render %}, gdy zawartość zawarta w moim widoku musi zostać odświeżona przy użyciu ajax. W ten sposób mogę wywołać tę samą akcję za pomocą standardowego routingu, gdy są interakcje na mojej stronie.

Rozważ prostą stronę z formularzem ajaxowym, który pomaga dodawać artykuły i dynamicznie odświeżany spis plików.

enter image description here

Jednostka cd

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

} 

Formie cd

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

} 

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

Regulatory

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

To daje pewną brzydką postać wygląda tak :

enter image description here

Chodzi o to, że jeśli odświeżysz swoją stronę lub dodasz/usuniesz materiał, ten sam kontroler zostanie wywołany.Nie trzeba tworzyć skomplikowanej logiki ani duplikować kodu.


{% include%} przykładem

Znacznik [% include %} pozwalają zawierać jakiś kawałek kodu gałązka o taki sam sposób jak dyspozycja include działa w PHP. To znaczy, w zasadzie: {% include %} daje drogę do ponownego użycia jakiegoś rodzajowe kawałek kodu w całej aplikacji.

enter image description here

Zatrzymamy się z naszym przykładzie do produkcji wyrobów: zachować StuffEntity i StuffData jednak wymienić następujące:

ułożenia:

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 } 

regulatorów:

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

Jak widać tutaj, jest tylko jeden kontroler, który zainicjować całych elementów strony (formy i tabeli), tak że nie jest możliwe do wykonania transakcji asynchronicznych . Możesz jednak dołączyć ten ogólny plik Table.html.twig w dowolnym miejscu aplikacji.


Wnioski

Będziesz korzystać {% render %} gdy widok wstawić mogą być odświeżane przy użyciu standardowej trasy lub gdy widok wstawić jest całkowicie niezależna od aktualnego kontekstu.

Będziesz używał {% include %}, gdy będziesz potrzebował użyć kilkukrotnego kodu twig w swojej aplikacji, ale będziesz musiał zainicjować wymagany kontekst widoku widoku w tej samej akcji, co macierzysty plik twig.

+0

Dzięki ja nie myślałem o Ajax, Twój answear dobrze pasuje do moich potrzeb! – 0x1gene

+0

Nie wiedziałem o tagu '{% render%}' w gałązce. Czy możesz wskazać mi wpis do dokumentu lub kilka próbek? Wydaje się naprawdę interesujący – SirDerpington

+0

Hmm, nie wygląda udokumentowane dużo, mają wygląd starego [Symfony2 doc] (http://symfony.com/doc/2.0/book/templating.html) i szukać sterowników Osadzanie ' '. –

Powiązane problemy