[英]How to import multiple macros?
我想从一个地方优雅地导入多个宏。
我创建了一个名为“ macros.twig”的文件,并将其包含在我的模板中:
{% include "_includes/macros" %}
在该文件中,我希望像这样导入所有可用的宏:
{% import "_includes/macros/snippets" as snippets %}
{% import "_includes/macros/timestamp" as timestamp %}
{% import "_includes/macros/telephone" as telephone %}
{% import "_includes/macros/subscribe" as subscribe %}
{% import "_includes/macros/image" as image %}
{% import "_includes/macros/admin" as admin %}
假设采用这种模块化方法可以更轻松地管理我要全局使用的宏。 而不会使我的主要布局混乱。
当前,当我以这种方式调用宏时,出现“变量“订阅”不存在”错误。
一次导入多个宏的首选方法是什么?
谢谢
Twig中的macro
标签是一种可以避免代码重复的功能,它用于具有{% import _self as macro %}
的单个模板,或用于使用相同视图变量的一组控制器的某些不同模板之间共享的模板。
如果需要在树枝中全局使用函数,则最好创建一个\\Twig_SimpleFunction
。
参见http://twig.sensiolabs.org/doc/advanced.html#functions和http://symfony.com/doc/current/cookbook/templating/twig_extension.html
无论如何,您可能会像这样自动加载宏:
<?php
// src/AppBundle/Twig/MacroAutoloadExtension.php
namespace AppBundle\Twig;
class MacroAutoloadExtension extends \Twig_Extension
{
public function getFunctions()
{
return array(
// "*"" is used to get "template_macro" as $macro as third argument
new \Twig_SimpleFunction('macro_*', array($this, 'getMacro'), array(
'needs_environment' => true, // $env first argument will render the macro
'needs_context' => true, // $context second argument an array of view vars
'is_safe' => array('html'), // function returns escaped html
'is_variadic' => true, // and takes any number of arguments
))
);
}
public function getMacro(\Twig_Environment $env, array $context, $macro, array $vars = array())
{
list($name, $func) = explode('_', $macro);
$notInContext = 0; // helps generate unique context key
$varToContextKey = function ($var) use (&$context, $name, $func, &$notInContext) {
if (false !== $idx = array_search($var, $context, true)) {
return $idx;
}
// else the var does not belong to context
$key = '_'.$name.'_'.$func.'_'.++$notInContext;
$context[$key] = $var;
return $key;
};
$args = implode(', ', array_map($varToContextKey, $vars));
$twig = <<<EOT
{% import '_includes/macros/$name.twig' as $name %}
{{ $name.$func($args) }}
EOT;
try {
$html = $env->createTemplate($twig)->render($context);
} catch (\Twig_Error $e) {
$e->setTemplateFile(sprintf('_includes/macro/%s.twig', $name));
throw $e;
}
return $html;
}
public function getName()
{
return 'macro_autoload_extension';
}
}
注册扩展名:
# app/config/sevices.yml services: ... app.macro_autoload_extension: class: AppBundle\\Twig\\MacroAutoloadExtension public: false tags: - { name: twig.extension }
写一些宏:
{% set hash = { 'one': 1, 'two': 'deux', 'posts': posts } %}
{{ macro_list_ul(hash) }}
{{ macro_list_ol(['un', 'deux', 'trois']) }}
要么:
{% set hash = { 'one': 1, 'two': 'deux', 'posts': posts } %} {{ macro_list_ul(hash) }}
通常,当您使用_self
或从另一个模板导入模板(一个文件)中的宏时,如果您需要set标签中的宏,则该宏不可用,因为set
标签的作用域与_self
不同(即使它共享上下文) :
{# /app/Resources/views/includes/macro/outer.html.twig #} {% macro function(args) %} ... {% endmacro %}
加
{# /app/Resources/views/Bundle/Controller/action.html.twig #} {% macro inner_macro(arg1, arg2) %} {# render something #} {# cannot access context of this view, only args #} {% endmacro %} {% import _self as inner %} {% import '/includes/macro/outer_macro.html.twig' as outer %} {# cannot access context either %} ... {% set some_var %} {# can access context but neither outer or inner #} {{ inner.inner_macro('yes', 64) }} {# will not work #} {# you need to do import _self as inner again %} {# this is fix by both my answer and the one by @KalZekdor #} {{ macro_outer_function(var_from_context) }} {# will work #} {% endset %} {{ some_var }}
您甚至可以在不使用导入的情况下从宏调用宏。
我创建了一个要点
同样,这对我来说有点困难,但是我将一个很好的捆绑包与一个自动加载宏的事件监听器放在一起。
namespace App\Common\UIExtensionBundle\Listeners;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Bundle\TwigBundle\TwigEngine;
class UIExtenderListener
{
private $macroNamespace = 'ui';
public function __construct(\Twig_Environment $oTwig, $aMacros)
{
$this->twig = $oTwig;
//Macros
$this->macros = $aMacros;
}
public function onKernelRequest(GetResponseEvent $oEvent)
{
$templates = [];
foreach ($this->macros as $macro => $template)
{
$templates[$macro] = $this->twig->loadTemplate($template);
}
$this->twig->addGlobal($this->macroNamespace, $templates);
}
}
捆绑软件的services.xml:
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="uiext.macros" type="collection">
<parameter key="test">UIXBundle:ui:test.html.twig</parameter>
<parameter key="list">UIXBundle:ui:list.html.twig</parameter>
<parameter key="entity">UIXBundle:ui:entity.html.twig</parameter>
</parameter>
</parameters>
<services>
<service id="uiext.extender" class="App\Common\UIExtensionBundle\Listeners\UIExtenderListener" scope="container">
<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="1000" />
<argument type="service" id="twig"/>
<argument>%uiext.macros%</argument>
</service>
</services>
</container>
这是views\\ui\\list.html.twig
文件:
{% macro ol(arr) %}
<ol>
{% for item in arr %}
<li>{{ item }}</li>
{% endfor %}
</ol>
{% endmacro %}
{% macro ul(arr) %}
<ul>
{% for item in arr %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endmacro %}
然后,从任何树枝模板中,只需添加{{ ui.list.ul(listArr) }}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.