Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php Symfony和Twig模板。如何动态扩展模板或不扩展任何内容?_Php_Symfony_Templates_Twig - Fatal编程技术网

Php Symfony和Twig模板。如何动态扩展模板或不扩展任何内容?

Php Symfony和Twig模板。如何动态扩展模板或不扩展任何内容?,php,symfony,templates,twig,Php,Symfony,Templates,Twig,让我描述一种情况。您有一个配置文件表单和一个用户可以上传个人配置文件相关文档的表单。由于配置文件表单已经很长,文档将移动到新表单 一切都很好。现在我们想使用引导选项卡来创建用户友好的概要文件 现在我知道了,因为我们使用两个单独的表单,如果您提交文档,配置文件上的更改将不会保存,反之亦然 我已使用在选项卡中添加了文档表单 <div role="tabpanel" class="tab-pane" id="documents"> {{ render(controller('Man

让我描述一种情况。您有一个配置文件表单和一个用户可以上传个人配置文件相关文档的表单。由于配置文件表单已经很长,文档将移动到新表单

一切都很好。现在我们想使用引导选项卡来创建用户友好的概要文件

现在我知道了,因为我们使用两个单独的表单,如果您提交文档,配置文件上的更改将不会保存,反之亦然

我已使用在选项卡中添加了文档表单

<div role="tabpanel" class="tab-pane" id="documents">
    {{ render(controller('ManyAppBundle:Document:createDocument', {'viewOnly': true})) }}
</div>
这就产生了问题,因为您不能在if中使用extends(导致节点“Twig_Node”“不存在节点“1”)错误)

其他类似的问题提供了这个解决方案

{% extends viewOnly == false ? ... %}
当viewOnly为false时,它必须扩展所有其他模板使用的基础模板,但如果为true,我只想显示以下内容:

{{ form_start(form, { 'style': 'horizontal', 'col_size': 'sm' }) }}
    {% if form.documents is defined %}
        {{ form_row(form.documents) }}
    {% endif %}

    {{ form_row(form.submit, { 'attr': { 'class': 'btn btn-success' } }) }}
{{ form_end(form) }}
但现在是在顶部

{% extends viewOnly == false ? ... %}
如果viewOnly变为true,则会失败,无法找到模板“”

有没有一种方法可以说扩展了这个特定的模板,这与不扩展任何模板的结果相同


或者,当viewOnly为false或什么也不做时,是否有一种方式表示扩展此功能?

逻辑应位于控制器操作中

您可以创建两个细枝,一个父细枝扩展并包含另一个包含数据的子细枝

在控制器中,可以根据条件渲染延伸的细枝或子细枝

在您的情况下,控制器代码可能如下所示:

if ($request->query->get('view-only') === true) {
    return $this->render('MyAppBundle:Default:data.html.twig'); // this twig hasn't extended; only data.
}
else {
    return $this->render('MyAppBundle:Default:index.html.twig'); // this twig has data.html.twig included and extended.
}

我希望这能解决您的问题。:)

虽然我更喜欢吉特的解决方案,但这里有一个更复杂的选择。请记住,这个解决方案只是教育性的

  • (如果您还没有)
  • 进入你的分机
  • 创建一个Twig函数
    extend_from
    (示例代码见下文),该函数根据请求返回模板
  • 在extend块中调用Twig函数
  • 细枝函数可能如下所示:

    /**
     * Returns the template to be extended
     * Notes: Code assumes that the request data is a protected property
     *        on the Twig extension.
     *
     * @param  string  $template = "full.html.twig"  the full layout template
     * @return string  the template to be extended
     */
    public function extendFrom($template = "full.html.twig")
    {
        if ($this->request->query->get('view-only') === true) {
            return "empty_layout.html.twig";
        }
    
        return $template;
    }
    
    在模板中:

    {# Templates assumes that your extended templates have a "content block" #}
    {% extends extend_from() %}
    
    {% block content %}
        {# Your template content here #}
    {% endblock %}
    
    这对我来说是一个“神奇”的解决方案。最好的方法是把你的内容看作一个模块。可以单独渲染,也可以将其包含到布局中

    例如:

  • 我创造了一个+a
  • 页面模板包括部分模板,其中包括一组模块
  • 当用户在站点周围导航时,我使用ajax并在已经呈现的页面中加载部分模板
  • 将来,我可以呈现整个页面、页面的一部分或该页面中的一个模块


    这有点复杂,但它变得非常强大,允许我覆盖任何模板。

    基本上有3种解决方案来确定如何在一个细枝模板中扩展不同类型的模板之间切换

    第一种是非常简单的基于真或假的逻辑。您可以在细枝文件中轻松地执行此操作,如以下示例所示

    {% extends entity.isExpired == false ? active.html.twig : expired.html.twig %}
    
    /* User Controller */
    public function showAction($id)
    {
        $user = $this->get('myapp.repository.user')->findBy($id);
        $isUser = $user instanceof User;
    
        if (!$isUser) {
            return $this->redirectToBloggersPage();
        }
    
        /* $params is what you will normally return to the template */
        $params = array (
            'user' => $user,
        );
    
        if ($user->hasPostedBlog()) {
            $params['blog'] = $this->get('myapp.repository.blog')->findByUserLatest($user);
    
            return $this->render('MyAppBundle:User:user_and_blog_view.html.twig', $params);
        }
        else {
            return $this->render('MyAppBundle:User:user_view.html.twig', $params);
        }
    }
    
    /* Twig extension */
    public function extendBookForm()
    {
        if ($this->getSecurityContext()->isGranted('IS_AUTHENTICATED_FULLY')) {
            return "user_view.html.twig";
        }
    
        return "public_view.html.twig";
    }
    
    /* Twig file */
    {% extends extend_book_from() %}
    
    第二个将是@Jeet建议在控制器中执行此操作。这也可以与布尔检查一样简单,但与以下示例中的其他实体检查一样高级

    {% extends entity.isExpired == false ? active.html.twig : expired.html.twig %}
    
    /* User Controller */
    public function showAction($id)
    {
        $user = $this->get('myapp.repository.user')->findBy($id);
        $isUser = $user instanceof User;
    
        if (!$isUser) {
            return $this->redirectToBloggersPage();
        }
    
        /* $params is what you will normally return to the template */
        $params = array (
            'user' => $user,
        );
    
        if ($user->hasPostedBlog()) {
            $params['blog'] = $this->get('myapp.repository.blog')->findByUserLatest($user);
    
            return $this->render('MyAppBundle:User:user_and_blog_view.html.twig', $params);
        }
        else {
            return $this->render('MyAppBundle:User:user_view.html.twig', $params);
        }
    }
    
    /* Twig extension */
    public function extendBookForm()
    {
        if ($this->getSecurityContext()->isGranted('IS_AUTHENTICATED_FULLY')) {
            return "user_view.html.twig";
        }
    
        return "public_view.html.twig";
    }
    
    /* Twig file */
    {% extends extend_book_from() %}
    
    第三个将是@Thomas建议在单独的细枝函数中执行此操作。这将在细枝扩展中完成,您可以在其中注入服务,如下面的示例所示

    {% extends entity.isExpired == false ? active.html.twig : expired.html.twig %}
    
    /* User Controller */
    public function showAction($id)
    {
        $user = $this->get('myapp.repository.user')->findBy($id);
        $isUser = $user instanceof User;
    
        if (!$isUser) {
            return $this->redirectToBloggersPage();
        }
    
        /* $params is what you will normally return to the template */
        $params = array (
            'user' => $user,
        );
    
        if ($user->hasPostedBlog()) {
            $params['blog'] = $this->get('myapp.repository.blog')->findByUserLatest($user);
    
            return $this->render('MyAppBundle:User:user_and_blog_view.html.twig', $params);
        }
        else {
            return $this->render('MyAppBundle:User:user_view.html.twig', $params);
        }
    }
    
    /* Twig extension */
    public function extendBookForm()
    {
        if ($this->getSecurityContext()->isGranted('IS_AUTHENTICATED_FULLY')) {
            return "user_view.html.twig";
        }
    
        return "public_view.html.twig";
    }
    
    /* Twig file */
    {% extends extend_book_from() %}
    
    我最初的问题没有解决我想要的结果。我认为我所希望的方式是不可能的,如果您想动态地检查要扩展的内容,您必须始终扩展多个模板,因为您必须为每个结果扩展某些内容


    这些是进行动态模板扩展的不同方法。

    我解决这个问题的方法是创建一个空的.html视图,其中只包含这个

    {% block content %}
    {% endblock %}
    

    这不是一个很好的解决方案,但比其他一些方法简单得多,因此我不必添加更多的混乱。

    主要问题是,当您创建一个新模板而不调用extends时,没有任何东西,甚至连引导代码都没有。它实际上只是将这个糟糕的默认值全部赋予左侧未格式化布局。我想要这个,我不想做一个新的模板,它不定义任何东西,也不想扩展这个模板。有没有一种方法可以说扩展了这一点,或者说不要试图扩展任何东西呢?上述解决方案不应该让您在刷新页面请求时获得未扩展的小枝。我猜如果是对选项卡数据的ajax请求,那么请求参数“view only”是可用的,在这种情况下,您必须只返回数据,而不是整个页面布局。因此,当ajax请求通过时,控制器操作中的上述条件会相应地影响到您。好的@Jeet我知道这一部分创建了两个模板,其中一个扩展了main,另一个只显示数据,但是如果您必须执行大多数main,那么在模板中执行非控制器逻辑有什么意义呢模板逻辑仍在控制器中?这感觉不是最好的。您的建议将导致3个小树枝文件,其中一个包含表单及其布局,另一个将包含扩展。。。包括(形式),第三个遗嘱只包括(形式)。你明白为什么我认为一定有另一种解决方案吗?我选择上面的解决方案是因为带包装器的扩展细枝元素可以与ajax返回的html格式的数据分离,如果有另一种解决方案,那就很好了。:)此外,我不认为需要第三个分支,除非您的ajax调用需要任何不同的数据集。在@Jeet给出第一个答案后,我相信我的问题没有明确说明。如果不扩展另一个模板,则默认情况下,所有内容都位于左侧,没有样式外观。这就是我想要的,我想用一种方式说,如果这扩展了这个,其他的什么都不做。如果它不打算扩展模板,那么它就不能尝试扩展任何内容。创建一个新的模板文件,但不包含任何内容