Подтвердить что ты не робот

Функция twig-pass в шаблон

В настоящее время я помещаю свою функцию в класс и передаю экземпляр этого класса в шаблон и вызываю свою требуемую функцию как метод класса.

{{ unneededclass.blah() }}

Мне нужно сделать, как показано ниже

{{ blah() }}

Возможно ли это?

4b9b3361

Ответ 1

Обновление 5/14/2015

Комментирующие отмечают, что я в основном ошибаюсь. Если вам действительно нужна функция, а не фильтр или макрос, вы можете сделать это, как было предложено в документах Twig:

$twig = new Twig_Environment($loader);
$function = new Twig_SimpleFunction('blah', function () {
   // ...
});
$twig->addFunction($function);

И используйте как

{{ blah() }}

Короче говоря, нет, это невозможно.

Однако надежда не потеряна!

Фильтры

Если эта функция blah() вашего предназначена для изменения существующей переменной, то это фильтр.

Пример:

//in your PHP
function format_date($date_string,$format_string) {
    return date($format_string,strtotime($date_string));
}
$twig_env->addFilter('format_date',new Twig_Filter_Function('format_date'));

{# in your template #}
{{ some_date|format_date('n/j/Y') }}

(Первый аргумент - это переменная, которую вы фильтруете, вторая - обычным способом)

Макросы

Если, как вы указали выше, ваша функция просто выводит HTML, то это хороший кандидат для макроса.

Пример:

{# in your template #}
{% macro say_hello() %}
<p>Oh! Hello, world!</p>
{% endmacro %}

{# ... later on ... #}
{{ _self.say_hello() }}

Или с параметрами:

{% macro input(name,value,type) %}
<input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value }}">
{% endmacro %}

{{ _self.input('phone_number','867-5309') }}
{{ _self.input('subscribe','yes','checkbox') }}

Почему?

Следует помнить, что шаблоны Twig представляют собой представление с точки зрения MVC. Это означает, что они изолированы по своей среде и могут представлять только контекст, который вы передаете через массив данных, который вы передаете в методе $template->render().

Это хорошо, поскольку он отделяет вашу презентацию от вашей логики и данных. Если вы можете произвольно называть функции, то вы внезапно увеличиваете эту связь, что плохо.

Другая причина в том, как PHP обрабатывает обратные вызовы. Подумайте, как вы должны были бы передать эту функцию в свой шаблон... Возможно, что-то вроде этого:

function blah() {
    return "<p>Oh! Hello, world!</p>";
}

$template = $twig_env->loadTemplate('template.html');
echo $template->render(array('blah'=>'blah'));

В вашем шаблоне контекстная переменная blah теперь представляет собой только строку, содержащую 'blah'.

В ванильном PHP, когда вы используете переменные функции, подобные этому (попробуйте использовать строковую переменную, как функцию), она (более или менее) выполняет поиск этой функции, а затем вызывает ее. Вы не передаете функцию, просто ее имя.

Дело в том, что вы не можете передать функцию в шаблон, потому что для этого используется только механизм только для PHP, это имя-строка и один раз внутри шаблона, это имя больше не является именем функции и просто строка.забастовкa >

Немного длинный, но я надеюсь, что это поможет!

Если вам нужна дополнительная документация, официальные документы здесь.

Ответ 2

Я был так же потерян, как и ты, мой друг, но после поиска в Интернете ответа и не нашел его, я решил посмотреть, смогу ли я сделать это сам. Поэтому я хотел опубликовать свое решение здесь (хотя я знаю, что этот пост старый), потому что это первый хит в google, если вы ищете эту проблему.

Вот так, на самом деле это довольно просто:

Я создал класс, который содержит мои функции и переменные, например:

class functionContainer{
        function getRandomNumber()
        {
                return rand();
        }
}
$values = array(
'functions'=> new functionContainer()
);

Итак, теперь у нас есть значения $как массив, который содержит этот объект с функцией "getRandomNumber()".

При рендеринге файла шаблона включите этот класс в значение:

$twig->render('random.html', $values);

Таким образом, внутри файла шаблона вы можете просто вызвать этот метод, чтобы вызвать функцию и получить результат:

{{ functions.getRandomNumber }}

Ответ 3

Хотя вы не можете напрямую обращаться к PHP, веточка расширяема. Вы можете добавить вызываемый фильтр, чтобы вы могли применить к функциям PHP, переданным в шаблон.

namespace My\Twig\Extension;

class LambdaFilter exnteds \Twig_Extension {

    public function getName() {
        return 'lambda_filter';
    }

    public function getFilters() {
        return array(
            new \Twig_SimpleFilter('call', array($this, 'doCall'))
        );
    }

    public function doCall() {
        $arguments = func_get_args();
        $callable = array_shift($arguments);
        if(!is_callable($callable)) {
            throw new InvalidArgumentException();
        }
        return call_user_func_array($callable, $arguments);
    }

}

Теперь, если вы передадите шаблон my_func в шаблон, вы можете сделать my_func|call(arg1, arg2). Вы даже можете выполнять функции более высокого порядка "array_filter"|call(my_array, my_func), и вы всегда можете делать больше вещей в фильтре, таких как прием массива, как параметры и т.д.

Ответ 4

Полный ответ: http://twig.sensiolabs.org/doc/advanced.html#id2

Я предпочитаю использовать расширение Twig следующим образом:

namespace Some\Twig\Extensions;

class MenuExtensions extends \Twig_Extension
{
    public function getFunctions()
    {
        return array(
            new \Twig_SimpleFunction('sidebar_menu', [$this, 'generate_sidebar_menu']),
        );
    }

    public function generate_sidebar_menu($menu){
        return $menu;
    }

    public function getName()
    {
        return 'menu';
    }
}

В шаблоне:

{{ sidebar_menu('some text') }}