dongleiwei2182 2014-11-04 14:32
浏览 71
已采纳

Twig:将对象变量从页面拉到自定义标签

I have making a custom twig tag called "story_get_adjacent" to get the next/prev articles based on the input id. But for the life of me I cant get the actual data from the object pulled into the tag for look up. it always gives me back the name not the data. I know this can be done because i tested it with the set tag and it returns the data not the name. Thoughts????

Object on page

Object >>
    Title = "This is a test story"
    StoryID = 1254
    Content ....

tag usage Example:

 {% story_get_adjacent Object.StoryID as adjacent %}

Twig Extension:

class Story_Get_Adjacent_TokenParser extends Twig_TokenParser
{
    public function parse(Twig_Token $token)
    {
        $parser = $this->parser; //story_get_adjacent
        $stream = $parser->getStream(); // space

        $value = $parser->getExpressionParser()->parseExpression(); //story id
        $names = array();
        try {
            $as = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); //as
            $ObjName = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); //object name
            array_push($names, $ObjName);
        } catch (Exception $e) {
            throw new Exception( 'error: ' . $e);
        }
        $stream->expect(Twig_Token::BLOCK_END_TYPE);
        return new Story_Get_Adjacent_Node($names, $value, $token->getLine(), $this->getTag());
    }

    public function getTag()
    {
        return 'story_get_adjacent';
    }
}

Twig Extension:

class Story_Get_Adjacent_Node extends Twig_Node
{
    public function __construct($name, Twig_Node_Expression $value, $line, $tag = null)
    {
        parent::__construct(array('value' => $value), array('name' => $name), $line, $tag);
    }

    public function compile (Twig_Compiler $compiler)
    {
        $Name     = $this->getAttribute('name')[0];
        $StoryAutoID    = $this->getNode('value')->getAttribute('value');

        $compiler->addDebugInfo($this);
        $compiler->write('$context[\''. $Name .'\'] = NewsController::TwigStoryGetAdjacent("'.$StoryAutoID.'");')->raw("
");
    }
}
  • 写回答

2条回答 默认 最新

  • douji4948 2014-11-06 23:10
    关注

    The problem is located in the compiler, when you try to access the value attribute of your expression.

    1. The expression parser need to be subcompiled into an expression in PHP.
    2. As the compiled expression is a non-evaluated expression, you shouldn't put quotes ( ' ) when you call TwigStoryGetAdjacent.

    Try with the following class:

    <?php
    
    class Story_Get_Adjacent_Node extends Twig_Node
    {
    
        public function __construct($name, Twig_Node_Expression $value, $line, $tag = null)
        {
            parent::__construct(array ('value' => $value), array ('name' => $name), $line, $tag);
        }
    
        public function compile(Twig_Compiler $compiler)
        {
            $Name = reset($this->getAttribute('name'));
    
            $compiler->addDebugInfo($this);
            $compiler
               ->write("\$context['$Name'] = NewsController::TwigStoryGetAdjacent(")
               ->subcompile($this->getNode('value'))
               ->write(");")
               ->raw("
    ")
            ;
        }
    
    }
    

    Working demo

    <kbd>test.php</kbd>

    <?php
    
    require(__DIR__ . '/vendor/autoload.php');
    
    require("TestExtension.php");
    require("TestTokenParser.php");
    require("TestNode.php");
    
    class NewsController
    {
    
        static public function TwigStoryGetAdjacent($id)
        {
            return "I return the story ID = {$id}.";
        }
    
    }
    
    $loader = new Twig_Loader_Filesystem('./');
    $twig = new Twig_Environment($loader, array (
            'cache' => __DIR__ . '/gen'
    ));
    
    $object = new \stdClass;
    $object->StoryID = 42;
    
    $twig->addExtension(new Test_Extension());
    echo $twig->render("test.twig", array ('Object' => $object));
    

    <kbd>test.twig</kbd>

    {% story_get_adjacent Object.StoryID as adjacent %}
    {{ adjacent }}
    

    <kbd>TestExtension.php</kbd>

    <?php
    
    class Test_Extension extends \Twig_Extension
    {
    
        public function getTokenParsers()
        {
            return array (
                    new Test_TokenParser(),
            );
        }
    
        public function getName()
        {
            return 'test';
        }
    
    }
    

    <kbd>TestTokenParser.php</kbd>

    <?php
    
    class Test_TokenParser extends Twig_TokenParser
    {
        public function parse(Twig_Token $token)
        {
            $parser = $this->parser; //story_get_adjacent
            $stream = $parser->getStream(); // space
    
            $value = $parser->getExpressionParser()->parseExpression(); //story id
            $names = array();
            try {
                $as = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); //as
                $ObjName = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); //object name
                array_push($names, $ObjName);
            } catch (Exception $e) {
                throw new Exception( 'error: ' . $e);
            }
            $stream->expect(Twig_Token::BLOCK_END_TYPE);
            return new Test_Node($names, $value, $token->getLine(), $this->getTag());
        }
    
        public function getTag()
        {
            return 'story_get_adjacent';
        }
    }
    

    <kbd>TestNode.php</kbd>

    <?php
    
    class Test_Node extends Twig_Node
    {
    
        public function __construct($name, Twig_Node_Expression $value, $line, $tag = null)
        {
            parent::__construct(array ('value' => $value), array ('name' => $name), $line, $tag);
        }
    
        public function compile(Twig_Compiler $compiler)
        {
            $Name = reset($this->getAttribute('name'));
    
            $compiler->addDebugInfo($this);
            $compiler
               ->write("\$context['$Name'] = NewsController::TwigStoryGetAdjacent(")
               ->subcompile($this->getNode('value'))
               ->write(");")
               ->raw("
    ")
            ;
        }
    
    }
    

    <kbd>Run</kbd>

    $ composer require "twig/twig" "~1.0"
    $ php test.php
    

    <kbd>Result</kbd>

    I return the story ID = 42.
    

    <kbd>Bonus</kbd> The compiled doDisplay method corresponding to the template

        protected function doDisplay(array $context, array $blocks = array())
        {
            // line 1
            $context['adjacent'] = NewsController::TwigStoryGetAdjacent($this->getAttribute((isset($context["Object"]) ? $context["Object"] : null), "StoryID", array())        );
            // line 2
            echo twig_escape_filter($this->env, (isset($context["adjacent"]) ? $context["adjacent"] : null), "html", null, true);
        }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 乌班图ip地址配置及远程SSH
  • ¥15 怎么让点阵屏显示静态爱心,用keiluVision5写出让点阵屏显示静态爱心的代码,越快越好
  • ¥15 PSPICE制作一个加法器
  • ¥15 javaweb项目无法正常跳转
  • ¥15 VMBox虚拟机无法访问
  • ¥15 skd显示找不到头文件
  • ¥15 机器视觉中图片中长度与真实长度的关系
  • ¥15 fastreport table 怎么只让每页的最下面和最顶部有横线
  • ¥15 R语言卸载之后无法重装,显示电脑存在下载某些较大二进制文件行为,怎么办
  • ¥15 java 的protected权限 ,问题在注释里