好的,首先是免责声明。我正在处理我的第一个 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