2

好的,首先是免责声明。我正在处理我的第一个 Sf2 项目并处理现有的 sf1 项目,将其重构为 Sf2 以了解所有抽屉已移至何处。

现在,发生了一些奇怪的事情,它让我扯掉了最后一根头发。

--- TL;DR:总结 ---

我正在从树枝模板渲染控制器并将数组传递给该子控制器。数组值之一是一个对象,但该对象在到达控制器之前就消失了。

我已经尽我所能通过 Symfony2 流程追踪它,并且我可以追踪到该对象是完整的。然后我迷路了,但是在 Symfony\Component\HttpKernel\Fragment\InlineFragmentRenderer::render() 和我的(子)控制器之间的某个地方,对象消失了。

这是一个功能,一个错误还是只是我发疯了?

- - 详细地 - -

我有一个 twig 模板,它处理一个实体对象(分配给 twig 变量“collection”),其中包含链接的实体,例如 imageItem 和 linkedPageItem)。

我的实体已设置为扩展实现 ArrayAccess 的基类,因此无论对象是否水合,我都可以使用数组表示法访问值。(遵循此处概述的选项#1 方法:http: //docs.doctrine-project.org/en/latest/cookbook/implementing-arrayaccess-for-domain-objects.html)。

在树枝中,我有一条这样的线,它将一些对象传递给子控制器以渲染图像块。renderImage 子控制器在渲染自己的树枝块之前管理所有内容的清理。

这是主树枝文件中的代码:

{# blockLinks.html.twig #}
...
{{- render(controller(
    'MyBundle:Helper:renderImage',
    {
        'image': collection['imageItem'], 
        'options': {
            'html_options': { 'class': 'foo' },
            'link_options': { 'class': 'bar' },
            'link_url':     collection['item_link_url'],
            'link_page':    collection['linkedPageItem']
        }
    }
)) -}}
...

但是,renderImage 子控制器永远不会收到 $options['link_page'] 的值。

这很奇怪,所以我更详细地研究了它。我找到了 twig 将 blockLinks.html.twig 渲染到的 PHP 文件,并对其进行了深入研究。

在那里我们发现:

// /app/cache/dev/twig/01/30/lotsofnumbers.php
...
echo $this->env->getExtension('http_kernel')->renderFragment($this->env->getExtension('http_kernel')->controller(
    "CaponicaFdsWebsiteBundle:Helper:renderImage", 
    array(
        "image" => $this->getAttribute($_collection_, "imageItem", array(), "array"), 
        "options" => array(
            "html_options" => array("class" => "foo"), 
            "link_options" => array("class" => "bar"),
            "link_url" => $this->getAttribute($_collection_, "item_link_url", array(), "array"), 
            "link_page" => $this->getAttribute($_collection_, "linkedPageItem", array(), "array")
        )
    )
));
...

好的,看起来不错。

为了弄清楚我做了什么\Doctrine\Common\Util\Debug::dump($this->getAttribute($_collection_, "linkedPageItem", array(), "array"));,它报告说这确实返回了一个 Page 对象。

即它报告类似:

object(stdClass)[874]
  public '__CLASS__' => string 'MyBundle\Entity\Page'
...

从缓存中编译的 twig php 文件开始
-> Symfony\Bridge\Twig\Extension\HttpKernelExtension::renderFragment()
-> Symfony\Component\HttpKernel\Fragment\FragmentHandler::render()
-> Symfony\Component\HttpKernel\Fragment \InlineFragmentRenderer::render()

此时对象仍然完好无损(通过在调用 $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false) 之前转储 $subRequest->attributes->get('options') 可以看到);在 InlineFragmentRenderer 的第 62 行)

我不确定接下来会去哪里。我以为它去了 [\vendor\symfony\symfony\src]Symfony\Bundle\FrameworkBundle\HttpKernel 但我似乎无法跟踪那里的任何活动。

但是,如果我查看 renderImage 控制器并转储如下选项:

// MyBundle\Controller\HelperController.php

public function renderImageAction($image, $options = array()) {
    print_r(\Doctrine\Common\Util\Debug::dump($options)); // I'm sure there's a 1337 way to use the logger/toolbar for this, I'll figure that out some other day
    ...
}

我明白了:

array (size=2)
  'html_options' => 
    array (size=1)
      'class' => string 'foo' (length=3)
  'link_options' => 
    array (size=1)
      'class' => string 'bar' (length=3)

换句话说,'link_page' 对象已经从选项中删除了——一些饥饿的东西(而且非常可怕)似乎潜伏在 Symfony 的深处并吃掉我的对象!

这是一个功能吗?(你不能将数组中的对象传递给子请求......也许这激怒了超级严格的 MVC 神?)
或者它是一个错误?(有些东西正在吃它不应该吃的东西?)
或者我只是把这根棍子弄错了?

我希望有人能帮忙,在我失去最后一根头发之前......

C

4

1 回答 1

0

将渲染函数与控制器函数结合使用时,您可以传递对象。我的意思是,它应该得到支持,并且应该按照您的方式工作。

但也许你遇到了和这个家伙一样的 bug,它似乎与 Doctrine2 对象特别相关:https ://github.com/symfony/symfony/issues/7124

于 2013-06-04T16:09:47.913 回答