programing

잔가지 템플릿에서 모든 변수를 검색하는 방법은 무엇입니까?

copysource 2023. 8. 23. 23:28
반응형

잔가지 템플릿에서 모든 변수를 검색하는 방법은 무엇입니까?

PHP로 Twig 템플릿 내의 모든 변수를 검색할 수 있습니까?

예: 일부 Template.twig.php:

Hello {{ name }}, 
your new email is {{ email }}

이제 저는 다음과 같은 것을 하고 싶습니다.

$template = $twig->loadTemplate('someTemplate');
$variables = $template->getVariables();

$dll에는 이제 "이름"과 "이메일"이 포함되어야 합니다.

제가 이것을 하고 싶은 이유는 사용자가 제 잔가지 템플릿과 변수를 동적으로 설정하고 API를 통해 변수를 채우는 CMS 시스템에서 일하고 있기 때문입니다.

기본값을 설정하지 않은 변수로 설정하고 싶으므로 템플릿 내에 존재하는 모든 변수의 목록이 필요합니다.

이 기능은 현재 컨텍스트에서 사용할 수 있는 모든 최상위 키를 가져오는 데 유용합니다.

<ol>
    {% for key, value in _context  %}
      <li>{{ key }}</li>
    {% endfor %}
</ol>

https://www.drupal.org/node/1906780 덕분입니다.

2019년 업데이트

비록 ~일지라도{{ dump() }}는 작동하며, 일부 상황에서는 PHP에서 너무 많은 정보를 생성할 경우(예: 재귀로 인해) "메모리 소진" 오류가 발생할 수 있습니다.경우에는 이경시도우를 시도해 .{{ dump(_context|keys) }}내용을 덤프하지 않고 이름별로 정의된 변수 목록을 가져옵니다.

2017년 업데이트

를 사용하면 가능합니다.{{ dump() }}지적합니다!댓글로 지적해 주셔서 감사합니다!


구식

불가능합니다.

이 이한변나뭇템지서에찾릿있다수니습추를 할 수 .|default('your_value')필터를 씌웁니다.변수가 정의되어 있고 비어 있지 않은지 확인하고, 그렇지 않은 경우 값으로 대체합니다.

내가 하는 방법은

<script>console.log({{ _context | json_encode | raw }});</script>

그런 다음 DevTools를 사용하여 콘솔을 확인합니다.

2015년 답변 추가

과거에는 그것이 불가능했습니다.그러나 버전 1.5 dump() 기능이 추가되었습니다.따라서 매개 변수 없이 현재 컨텍스트 호출 dump()에서 모든 변수를 가져올 수 있습니다.

<pre>
    {{ dump(user) }}
</pre>

그러나 Twig 환경을 생성할 때 Twig_Extension_Debug 확장을 명시적으로 추가해야 합니다.dump()기본적으로 사용할 수 없습니다.

$twig = new Twig_Environment($loader, array(
    'debug' => true,
    // ...
));
$twig->addExtension(new Twig_Extension_Debug());

했다면, 심니포등, 스사왔해다면용을, 실렉사▁sym,.dump()기본적으로 사용할 수 있습니다.

편집:

.dump()), 변수 ), 에 대해 설명합니다_context이것이 당신이 찾던 것입니다.모든 변수 이름을 값에 연결하는 배열입니다.

Twig 설명서에서 몇 가지 추가 정보를 찾을 수 있습니다.

그러나 이 특정 질문의 경우 검색이 번거롭지 않도록 현재 언급하고 있는 모든 사용자 지정 변수를 동일한 포괄 변수 아래에 수집하는 것이 가장 좋습니다.나는 이름이 붙은 배열이 될 것입니다.custom_variables뭐 그런 거.

모든 변수를 덤프하는 가장 좋은 방법과 가장 쉬운 방법은 다음과 같습니다.

{{ dump () }}

출처: https://www.drupal.org/docs/8/theming/twig/discovering-and-inspecting-variables-in-twig-templates

텍스트 내부에 모든 Twig 요소가 필요한 경우 다음을 사용합니다.

preg_match_all('/\{\%\s*(.*)\s*\%\}|\{\{(?!%)\s*((?:[^\s])*)\s*(?<!%)\}\}/i', $text, $matches);

WSIWYG 에디터가 Twig 변수 안에 HTML 태그를 넣는 문제가 있었습니다.다음을 사용하여 필터링:

public function cleanHTML($text)
{
    preg_match_all('/\{\%\s*(.*)\s*\%\}|\{\{(?!%)\s*((?:[^\s])*)\s*(?<!%)\}\}/i', $text, $matches);

    if (isset($matches[0]) && count($matches[0])) {
        foreach ($matches[0] as $match) {
            $clean_match = strip_tags($match);

            $text = str_replace($match, $clean_match, $text);
        }
    }

    return $text;
}

갱신하다

이 식을 사용하여 {{}} 및 {%%}을(를) 모두 찾습니다.

preg_match_all('/\{\%\s*([^\%\}]*)\s*\%\}|\{\{\s*([^\}\}]*)\s*\}\}/i', $text, $matches);

저는 19 Gerhard85의 답변이 꽤 좋다고 생각합니다. 비록 그것이 저에게 빈 문자열과 일치했기 때문에 약간의 수정이 필요할지도 모릅니다.저는 가능한 한 기존의 기능을 사용하는 것을 좋아하고 이것은 주로 나뭇가지의 기능을 사용하는 접근법입니다.애플리케이션의 세부 환경에 대한 액세스가 필요합니다.

/**
 * @param $twigTemplateName
 * @return array
 */
public function getRequiredKeys($twigTemplateName)
{
    $twig = $this->twig;
    $source = $twig->getLoader()->getSource($twigTemplateName);
    $tokens = $twig->tokenize($source);
    $parsed = $twig->getParser()->parse($tokens);
    $collected = [];
    $this->collectNodes($parsed, $collected);

    return array_keys($collected);
}

그리고 그것의 유일한 사용자 지정 부분은 특정 유형의 노드만 수집하는 재귀 함수입니다.

/**
 * @param \Twig_Node[] $nodes
 * @param array $collected
 */
private function collectNodes($nodes, array &$collected)
{
    foreach ($nodes as $node) {
        $childNodes = $node->getIterator()->getArrayCopy();
        if (!empty($childNodes)) {
            $this->collectNodes($childNodes, $collected); // recursion
        } elseif ($node instanceof \Twig_Node_Expression_Name) {
            $name = $node->getAttribute('name');
            $collected[$name] = $node; // ensure unique values
        }
    }
}

Duncan의 대답을 꽤 오랫동안 사용한 후에 저는 마침내 템플릿의 모든 가지 변수를 덤프하는 "올바른" 방법을 찾았습니다.

{% dump %}

바로 그겁니다.템플릿에서 사용할 수 있는 모든 변수는 다음과 같이 HTML의 중간이 아닌 프로파일러의 덤프 섹션에 덤프됩니다.{{ dump() }}.

의 ,dump()변수로:

{% set d = dump() %}

당신은 모든 변수를 얻을 수 있지만 "html 준비 완료" html에서는 그것을 구문 분석하는 것이 어려울 것입니다.

도움이 되길 바랍니다.

$loader1 = new Twig_Loader_Array([
    'blub.html' => '{{ twig.template.code }}',
]);
$twig = new Twig_Environment($loader1);
$tokens = $twig->tokenize($loader1->getSource('blub.html'));
$nodes = $twig->getParser()->parse($tokens);

var_dump($this->getTwigVariableNames($nodes));


function getTwigVariableNames($nodes): array
{
    $variables = [];
    foreach ($nodes as $node) {
        if ($node instanceof \Twig_Node_Expression_Name) {
            $name = $node->getAttribute('name');
            $variables[$name] = $name;
        } elseif ($node instanceof \Twig_Node_Expression_Constant && $nodes instanceof \Twig_Node_Expression_GetAttr) {
            $value = $node->getAttribute('value');
            if (!empty($value) && is_string($value)) {
                $variables[$value] = $value;
            }
        } elseif ($node instanceof \Twig_Node_Expression_GetAttr) {
            $path = implode('.', $this->getTwigVariableNames($node));
            if (!empty($path)) {
                $variables[$path] = $path;
            }
        } elseif ($node instanceof \Twig_Node) {
            $variables += $this->getTwigVariableNames($node);
        }
    }
    return $variables;
}

재미있게 놀아요 :-)

템플릿을 구문 분석하고 반환되는 AST를 통과해야 합니다.

$loaded = $twig->getLoader()->getSource($template);
var_dump(extractVars($twig->parse($twig->tokenize($loaded))));

function extractVars($node)
{
    if (!$node instanceof Traversable) return array();

    $vars = array();
    foreach ($node as $cur)
    {
        if (get_class($cur) != 'Twig_Node_Expression_Name')
        {
            $vars = array_merge($vars, call_user_func(__FUNCTION__, $cur));
        }
        else if ($cur->getAttribute('always_defined') == false)
        {
            // List only predefined variables expected by template, 
            // filtering out `v` and leaving `arr` from `{% for v in arr%}`
            $vars[] = $cur->getAttribute('name');
        }
    }

    return $vars;
}

Twig2Schema 클래스를 구축하여 Twig AST에서 변수를 추론했습니다.문서에서 변수를 가져오려면 Twig AST를 재귀적으로 "걸어서" 처리하고 특정 유형의 언어 노드가 발생할 때 규칙을 설정해야 합니다.

이 클래스는 변수 이름이 항상 정의되지 않은 경우 노드에서 변수 이름을 추출하고 ForLoopNodes 및 IfStatement에 사용된 값에서 변수를 가져옵니다.

사용하려면 전화를 걸어 주십시오.infer 전체해에음을 합 템 플 릿 다 사 용 합 니 대 다 집 하 위 또 트 의 리 는 ▁for 니 합 ▁using 다 , 용 ▁tree 사 ▁of ▁the ▁a 전 ▁or ▁subsetinferFromAst.

<?php

class Twig2Schema
{
    /**
     * @param \Twig\Environment $twig - A twig environment containing loaded templates
     * @param $twigTemplateName - The name of the template to infer variables from
     * @param $config - A configuration object for this function
     * @return array
     */
    public function infer(\Twig\Environment $twig, $twigTemplateName)
    {
        $source = $twig->getLoader()->getSourceContext($twigTemplateName);
        $tokens = $twig->tokenize($source);
        $ast = $twig->parse($tokens);
        return $this->inferFromAst($ast);
    }

    /**
     * @param \Twig\Node\ModuleNode $ast - An abstract syntax tree parsed from Twig
     * @return array - The variables used in the Twig template
     */
    public function inferFromAst(\Twig\Node\ModuleNode $ast)
    {
        $keys = $this->visit($ast);

        foreach ($keys as $key => $value) {
            if ($value['always_defined'] || $key === '_self') {
                unset($keys[$key]);
            }
        }

        return $keys;
    }

    /**
     * @param \Twig\Node\Node $ast - The tree to traverse and extract variables
     * @return array - The variables found in this tree
     */
    private function visit(\Twig\Node\Node $ast)
    {
        $vars = [];
        switch (get_class($ast)) {
            case \Twig\Node\Expression\AssignNameExpression::class:
            case \Twig\Node\Expression\NameExpression::class:
                $vars[$ast->getAttribute('name')] = [
                    'type' => get_class($ast),
                    'always_defined' => $ast->getAttribute('always_defined'),
                    'is_defined_test' => $ast->getAttribute('is_defined_test'),
                    'ignore_strict_check' => $ast->getAttribute('ignore_strict_check')
                ];
                break;
            case \Twig\Node\ForNode::class:
                foreach ($ast as $key => $node) {
                    switch ($key) {
                        case 'value_target':
                            $vars[$node->getAttribute('name')] = [
                                'for_loop_target' => true,
                                'always_defined' => $node->getAttribute('always_defined')
                            ];
                            break;
                        case 'body':
                            $vars = array_merge($vars, $this->visit($node));
                            break;
                        default:
                            break;
                    }
                }
                break;
            case \Twig\Node\IfNode::class:
                foreach ($ast->getNode('tests') as $key => $test) {
                    $vars = array_merge($vars, $this->visit($test));
                }
                foreach ($ast->getNode('else') as $key => $else) {
                    $vars = array_merge($vars, $this->visit($else));
                }
                break;
            default:
                if ($ast->count()) {
                    foreach ($ast as $key => $node) {
                        $vars = array_merge($vars, $this->visit($node));
                    }
                }
                break;
        }
        return $vars;
    }
}

제가 위의 모든 답변을 시도하면서 꽤 하룻밤을 보낸 후, 저는 예상치 못한 이유로 regexps가 제 단순한 템플릿에서 전혀 작동하지 않는다는 것을 깨달았습니다.정크 또는 부분 정보를 반환했습니다.그래서 저는 태그 ^_^을 세는 대신 태그 사이의 모든 내용을 지우는 것으로 가기로 결정했습니다.

내 말은, 만약 템플릿이'AAA {{BB}} CC {{DD}} {{BB}} SS'덧붙이자면'}}'템플릿의 시작 부분과'{{결국... 그리고 그 사이의 모든 내용들.}}그리고.{{그냥 옷을 벗고 중간에 콤마를 넣겠습니다 =>}}{{BB,}}{{DD,}}{{BB,}}{{그러면 - 그냥 지우기}}그리고.{{.

글을 쓰고 테스트하는 데 약 15분이 걸렸지만 정규식을 사용하여 약 5시간을 보냈지만 성공하지 못했습니다.

/**
 * deletes ALL the string contents between all the designated characters
 * @param $start - pattern start 
 * @param $end   - pattern end
 * @param $string - input string, 
 * @return mixed - string
 */
 function auxDeleteAllBetween($start, $end, $string) {
    // it helps to assembte comma dilimited strings
    $string = strtr($start. $string . $end, array($start => ','.$start, $end => chr(2)));
    $startPos  = 0;
    $endPos = strlen($string);
    while( $startPos !== false && $endPos !== false){
        $startPos = strpos($string, $start);
        $endPos = strpos($string, $end);
        if ($startPos === false || $endPos === false) {
            return $string;
        }
        $textToDelete = substr($string, $startPos, ($endPos + strlen($end)) - $startPos);
        $string = str_replace($textToDelete, '', $string);
    }
    return $string;
}

/**
 * This function is intended to replace
 * //preg_match_all('/\{\%\s*([^\%\}]*)\s*\%\}|\{\{\s*([^\}\}]*)\s*\}\}/i', 
 * which did not give intended results for some reason.
 *
 * @param $inputTpl
 * @return array
 */
private function auxGetAllTags($inputTpl){
   $inputTpl = strtr($inputTpl, array('}}' => ','.chr(1), '{{' => chr(2)));
   return explode(',',$this->auxDeleteAllBetween(chr(1),chr(2),$inputTpl));
}


$template = '<style>
td{border-bottom:1px solid #eee;}</style>
<p>Dear {{jedi}},<br>New {{padawan}} is waiting for your approval: </p>
<table border="0">
<tbody><tr><td><strong>Register as</strong></td><td>{{register_as}}, user-{{level}}</td></tr>
<tr><td><strong>Name</strong></td><td>{{first_name}} {{last_name}}</td></tr>...';

print_r($this->auxGetAllTags($template));

누군가에게 도움이 되길 바랍니다 :)

twig 컴파일 프로세스를 보면 twig 컴파일 프로세스에 ignore_strict_check라는 매개 변수가 있다는 것을 알 수 있습니다. twig/src/Node/Expression/NameExpression 파일이 누락된 변수를 null로 대체하지만, false 컴파일이 실행 시간 오류를 발생시킬 경우 파일 twig/src/Node/Node/Expression/NameExpression을 확인합니다.Symphony의 php line 63 당신은 twig 패키지 구성 strict_false: false를 통해 이 매개 변수를 설정할 수 있습니다.

Twig_Extension을 만들고 needs_context 플래그를 사용하여 함수를 추가합니다.

class MyTwigExtension extends Twig_Extension{
   public function getFunctions()
    {
        return array(
            new \Twig_SimpleFunction('myTwigFunction', array($this, 'myTwigFunction'), array('needs_context' => true)),
        );
    }

    public function myTwigFunction($context)
    {
        var_dump($context);
        return '';
    }
}

컨텍스트는 모든 변수를 포함하는 함수에 첫 번째 매개 변수로 전달됩니다.

Twig 템플릿에서 해당 함수를 호출하기만 하면 됩니다.

{{myTwigFunction()}}

Twig Extension을 만드는 데 도움이 필요한 경우 다음 문서를 참조하십시오.

http://twig.sensiolabs.org/doc/2.x/advanced.html

이 질문은 중복됩니다. 의 질문보다 유용하고 강력한 RegEX를 발견했습니다.이것은 좀 더 정확하게 일치하도록 개선되었습니다.

\{\{(?!%)\s* # Starts with {{ not followed by % followed by 0 or more spaces
  ((?:(?!\.)[^\s])*?) # Match anything without a point or space in it
  (\|(?:(?!\.)[^\s])*)? # Match filter within variable
\s*(?<!%)\}\} # Ends with 0 or more spaces not followed by % ending with }}
| # Or
\{%\s* # Starts with {% followed by 0 or more spaces
  (?:\s(?!endfor)|(endif)|(else)(\w+))+ # Match the last word which can not be endfor, endif or else
\s*%\} # Ends with 0 or more spaces followed by %}
# Flags: i: case insensitive matching | x: Turn on free-spacing mode to ignore whitespace between regex tokens, and allow # comments.

Twig 3.0에 대한 실제 솔루션을 준비합니다.

function visit(\Twig\Node\Node $node, &$variables)
{
    // @see https://github.com/twigphp/Twig/issues/2340 for details about NodeCaptureInterface
    if ($node instanceof \Twig\Node\NodeCaptureInterface) {
        return;
    }

    if ($node instanceof \Twig\Node\Expression\NameExpression
        && false === $node->getAttribute('always_defined') // ignore scoped names as (key, value) in for loop 
    ) {
        $variables[$node->getAttribute('name')] = null;

        return;
    }

    foreach ($node as $child) {
        visit($child, $variables);
    }
}

// @var Twig\Environment $twig

// create template from string
$template = 'my template {{ var }}';
$source = new \Twig\Source($template, 'template');
// or get from loader
// $source = $twig->getLoader()->getSourceContext('template.twig.html');

// tokenize and par
$tokens = $twig->tokenize($source);
$nodes = $twig->parse($tokens);

$variables = [];
visit($nodes, $variables);

var_dump(array_keys($variables));

언급URL : https://stackoverflow.com/questions/12799094/how-to-retrieve-all-variables-from-a-twig-template

반응형