我制作了一个名为" story_get_adjacent"的自定义树枝标签。根据输入ID获取下一篇/上一篇文章。但是对于我的生活,我无法将对象的实际数据拉入标签中以便查找。它总是让我回到名字而不是数据。我知道这可以做到,因为我用set标签测试了它,它返回的数据不是名字。思考????
页面上的对象
Object >>
Title = "This is a test story"
StoryID = 1254
Content ....
标签用法示例:
{% 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("\n");
}
}
答案 0 :(得分:3)
Alain Tiemblo解决了你的问题。但是,为什么你的生活如此艰难?为什么不简单地使用树枝功能呢?
{% set adjacent = story_get_adjacent(Object.StoryID) %}
class StoryExtension extends \Twig_Extension
{
public function getFunctions()
{
return array(
\Twig_SimpleFunction('story_get_adjacent', array($this, 'getAdjacent'), array('is_safe' => array('html'))),
);
}
public function getAdjacent($storyId)
{
return NewsController::TwigStoryGetAdjacent($storyId);
}
public function getName()
{
return 'story';
}
}
(is_safe
选项告诉twig它的安全HTML,因此您在使用{{ story_get_adjacent(Object.StoryID) }}
时不必禁用转义。
答案 1 :(得分:2)
当您尝试访问表达式的value属性时,问题出在编译器中。
'
时不应放置引号(TwigStoryGetAdjacent
)。尝试使用以下类:
<?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("\n")
;
}
}
test.php的
<?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));
test.twig
{% story_get_adjacent Object.StoryID as adjacent %}
{{ adjacent }}
TestExtension.php
<?php
class Test_Extension extends \Twig_Extension
{
public function getTokenParsers()
{
return array (
new Test_TokenParser(),
);
}
public function getName()
{
return 'test';
}
}
TestTokenParser.php
<?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';
}
}
TestNode.php
<?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("\n")
;
}
}
运行
$ composer require "twig/twig" "~1.0"
$ php test.php
结果
I return the story ID = 42.
奖金 与模板对应的已编译的doDisplay方法
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);
}