12

我读过Twig: render vs include但这不是我想要的。我不确定应该在何时何地使用渲染,何时应该使用包含,因为这些表达式的行为似乎与我非常相似。

这两种表达方式的根本区别是什么?

4

1 回答 1

51

{% render %}和之间存在重大差异{% include %}

  • {% render %}标签调用一个动作:当你这样做时,你正在执行一个控制器,在该控制器内创建一个新的上下文并呈现一个将添加到当前视图的视图。

  • {% include %}标签在当前文件中包含另一个树枝文件:没有调用任何操作,因此包含的文件将使用您当前的上下文(或您作为参数提供的上下文)来呈现视图。

让我们详细看看。


{% 渲染 %} 示例

Render 是一个标签,它调用一个动作的方式与使用路由调用它的方式非常相似,但在内部,没有 HTTP 事务。就个人而言,{% render %}当我的视图中包含的内容需要使用 ajax 刷新时,我会使用它。这样,当我的页面内有交互时,我可以使用标准路由调用相同的操作。

考虑一个简单的页面,它有一个 ajax 表单,可以帮助您添加东西,以及一个动态刷新的东西表。

在此处输入图像描述

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

}

资料表格

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

这会给你一些看起来像这样的丑陋形式:

在此处输入图像描述

关键是:如果您刷新页面或添加/删除内容,将调用相同的控制器。无需创建一些复杂的逻辑或复制代码。


{% include %} 示例

[% include %}标签允许您包含一些树枝代码,其方式与includePHP 中的指令工作方式大致相同。这基本上意味着:为您提供了一种在应用程序中随处{% include %}重用一些通用代码的方法。

在此处输入图像描述

我们继续使用我们的 stuffs 示例:保留 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,
    }
%}

通用表:

{# 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 %}当您需要在应用程序中多次使用一条 twig 代码时,您将使用该代码,但您需要在与父 twig 文件相同的操作中初始化包含的视图所需的上下文。

于 2013-04-30T11:38:12.380 回答