加载视图而不渲染

时间:2013-01-07 17:26:53

标签: php symfony-2.1

我的Symfony项目中有一个Twig扩展,它呈现了一个推特小部件。目前,在我的扩展中,我有这个:

public function twitter($handle, $number = 5)
{
    return "<div data-tweet-row=\"&lt;div&gt;&lt;a  href='http://twitter.com/{screen_name}/status/{id}'&gt;{tweet}&lt;/a&gt;&lt;span class='datetime'&gt;{datetime}&lt;/span&gt;&lt;/div&gt;\" data-twitter-header=\"&lt;div class='header'&gt;&lt;img src='https://api.twitter.com/1/users/profile_image?screen_name={screen_name}&amp;size=normal' /&gt;&lt;h4&gt;&lt;a href='http://twitter.com/{screen_name}'&gt;@{screen_name}&lt;/a&gt;&lt;/h4&gt;&lt;/div&gt;\" id=\"twitter\">&nbsp;</div><script>$('#twitter').biff_twitter({screen_name:'$handle',count:$number});</script>";
}

但是我真的不喜欢这个解决方案,我宁愿在views下保存HTML,然后从我的扩展程序中加载文件。

我可以使用以下方式从扩展程序中访问容器:

private $container;

public function __construct(ContainerInterface $container){
    $this->container = $container;
}

所以我需要像

这样的东西
$view_file = $this->container->get('...')->view('InternalSocialBundle:twitter_placeholder.html.twig')

2 个答案:

答案 0 :(得分:1)

当然你完全正确。您要查找的服务名称为templating。 所以这对你有用:

$html = $this->container->get('templating')->render('InternalSocialBundle:twitter_placeholder.html.twig');

修改

这是一个有效的例子:

class FooExtension extends \Twig_Extension
{
    private $container;

    public function setContainer(\Symfony\Component\DependencyInjection\Container $container)
    {
        $this->container = $container;
    }

    public function foo()
    {
        return $this->container->get('templating')->render('CogiPortfolioBundle:Portfolio:tmp.html.twig');
    }

    public function getFunctions()
    {
        return array(
            'foo' => new \Twig_Function_Method($this, 'foo', array('is_safe' => array('html')))
        );
    }

    /* (...) */
}

服务定义:

<service id="cogi.foo.ext" class="Cogi\PortfolioBundle\TwigExtension\FooExtension">
    <call method="setContainer">
        <argument type="service" id="service_container" />
    </call>
    <tag name="twig.extension" />
</service>

知道我是否在任何模板中调用{{foo()}}它会从tmp.twig.html呈现html。而在另一方面 - 如果在我的扩展中,我将“路径”放在render方法中的非现有模板中,则会抛出异常。

我希望这会有所帮助。

答案 1 :(得分:1)

好的,所以我解决了我遇到的问题但是没有完全测试这是我的错。 @ Cyprian的解决方案在你没有做任何复杂的事情并且只是按预期使用扩展时确实可以正常工作。

我的问题是我正在使用这个从数据库加载模板的evaluate extension,因此它正在进行所有加载(因此仅解释{{1}的第一个参数}作为$this->render() - 它没有尝试使用symfony命名模式加载它。)

这意味着在实际的twig文件中使用上述方法时,我的扩展程序可以正常工作,但在我使用string扩展名时则不行。

该问题的解决方案如下:

在我的services.yml文件中,我不仅需要{{body|evaluate}},还需要service_container所以它看起来很像:

twig.loader

然后我将此作为twig扩展构造函数:

class: Test\SocialBundle\Twig\SocialExtension
arguments: [@service_container,@twig.loader]
tags:
    -  { name: 'twig.extension' }

在我的public function __construct(ContainerInterface $container, \Symfony\Bundle\TwigBundle\Loader\FilesystemLoader $loader) { $this->container = $container; $this->loader = $loader; } 定义中:

getFilters()

最后,在我返回渲染输出之前:

public function getFilters()
{
  return array(
    'twitter' => new \Twig_Filter_Method($this, 'twitter',array(
        'is_safe' => array(
            'evaluate' => true
            ),
        'needs_environment' => true,
        )
    )
  )
}

这确保了我一直在使用public function twitter(\Twig_Environment $environment, $id) { $social_item = array(); // get my data here from my service; $environment->setLoader($this->loader); return $environment->render("TestSocialBundle:Front:twitter_placeholder.html.twig",array()); } 加载器,而不是\Symfony\Bundle\TwigBundle\Loader\FilesystemLoader在我的情况下使用。