我正在使用Kohana 3.3,并尝试将页面输出到菜单和所有子菜单。子菜单与页面存储在同一个表中,称为页面。一个页面和一个子菜单之间唯一的区别是一个标志。这是页面的表结构,以及我创建的示例页面。
| id | title | layout | content | is_menu | parent | position |
| 1 | Home | home.php | Lipsum... | 0 | 0 | 1 |
| 3 | Menu1 | none | | 1 | 0 | 2 |
| 2 | Expl1 | view.php | Lipsum... | 0 | 0 | 3 |
| 5 | MPge2 | view.php | Lipsum... | 0 | 3 | 1 |
| 4 | MPge1 | view.php | Lipsum... | 0 | 3 | 2 |我将所有页面作为ORM对象加载到一个数组中,按父对象排序,然后定位。当查询获取它们时,我已经对上面的表进行了排序。这是我的PHP方法,用于生成HTML菜单,然后将ORM页面数组传递给该菜单:
class Controller_Page extends Controller_Table {
/**
* Ourput the menu for editing purposes. Include add new page buttons.
*
* @return body
*/
public function action_acp_menu()
{
$view = View::factory('acp/layouts/pages/menu')
->bind('menu_pages', $menu_pages);
$pages = ORM::factory('Page')
->order_by('parent')
->order_by('position')
->find_all();
$menu_pages = $this->menu($pages);
$this->response->body($view->render());
}
/**
* Output the pages in a menu format, with optional add more buttons if
* we're in the ACP. This returns a string of LIs without a wrapping UL.
*
* @param ORM $pages ORM object of pages.
* @param integer $parent Output all children of this parent.
* @return string
*/
private function menu($pages, $parent = 0)
{
$html = '';
$is_acp = (strpos(Request::initial()->uri(), 'acp') !== FALSE);
echo "<br>Testing pages against parent: $parent<br>";
foreach ($pages as $page)
{
echo "Page: ".$page->id."; Parent: ".$page->parent."<br>";
if ($page->parent == $parent)
{
echo "Page belongs to the parent.<br>";
if ($page->is_menu)
{
echo "Page ".$page->id." is a menu. Loading children.<br>";
$children = $this->menu($pages, $page->id);
if ($children OR $is_acp)
{
echo "Children found (or we're in the ACP). Adding pages to the menu.<br>";
$html .= '<li class="dropdown" data-id="'.$page->id.'">'.($is_acp ? '
<span class="handle">::</span>' : '').'
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
'.$page->title.'
<b class="caret"></b>
</a>
<ul class="dropdown-menu'.($is_acp ? ' sortable-child' : '').'" data-id="'.$page->id.'">
'.$children.'
</ul>
</li>';
}
}
else
{
echo "Page ".$page->id." is not a menu. Outputting normal.<br>";
$html .= '<li data-id="'.$page->id.'">'.($is_acp ? '
<span class="handle">::</span>' : '').'
<a href="/acp/pages/edit'.$page->id.'">'.$page->title.'</a>
</li>';
}
}
echo "Finished processing page ".$page->id."<br>";
}
echo "Finished looping all pages<br>";
if ($is_acp)
{
$html .= '<li class="add-page">
<a href="/acp/pages/create?parent='.$page->id.'">+ Add page</a>
</li>';
}
echo "Finished testing against parent: $parent<br>";
return $html;
}如你所见,我放了一堆echo来试着弄清楚是怎么回事。这是所有回声的输出:
Testing pages against parent: 0
Page: 1; Parent: 0
Page belongs to the parent.
Page 1 is not a menu. Outputting normal.
Finished processing page 1
Page: 3; Parent: 0
Page belongs to the parent.
Page 3 is a menu. Loading children.
Testing pages against parent: 3
Page: 1; Parent: 0
Finished processing page 1
Page: 3; Parent: 0
Finished processing page 3
Page: 2; Parent: 0
Finished processing page 2
Page: 5; Parent: 3
Page belongs to the parent.
Page 5 is not a menu. Outputting normal.
Finished processing page 5
Page: 4; Parent: 3
Page belongs to the parent.
Page 4 is not a menu. Outputting normal.
Finished processing page 4
Finished looping all pages
Finished testing against parent: 3
Children found (or we're in the ACP). Adding pages to the menu.
Finished processing page 3
Finished looping all pages
Finished testing against parent: 0因此,在第二次调用子菜单(ID3)的menu方法之后,foreach循环完成了ID3,但不会继续到下一页。我不明白为什么?我以前做过这样的foreach循环,但效果很好,这是我第一次在Kohana中这样做,所以我认为这是Kohana相关的事情,我不明白。
我已经创建了一个eval.in of this,展示了代码的工作方式,并且它一定是Kohana中的某个东西在做这件事。这是来自eval.in的所有回声的结果:
Testing pages against parent: 0
Page: 1; Parent: 0
Page belongs to the parent.
Page 1 is not a menu. Outputting normal.
Finished processing page 1
Page: 3; Parent: 0
Page belongs to the parent.
Page 3 is a menu. Loading children.
Testing pages against parent: 3
Page: 1; Parent: 0
Finished processing page 1
Page: 3; Parent: 0
Finished processing page 3
Page: 2; Parent: 0
Finished processing page 2
Page: 5; Parent: 3
Page belongs to the parent.
Page 5 is not a menu. Outputting normal.
Finished processing page 5
Page: 4; Parent: 3
Page belongs to the parent.
Page 4 is not a menu. Outputting normal.
Finished processing page 4
Finished looping all pages
Finished testing against parent: 3
Children found (or we're in the ACP). Adding pages to the menu.<br>
Finished processing page 3
Page: 2; Parent: 0
Page belongs to the parent.
Page 2 is not a menu. Outputting normal.
Finished processing page 2
Page: 5; Parent: 3
Finished processing page 5
Page: 4; Parent: 3
Finished processing page 4
Finished looping all pages
Finished testing against parent: 0正如您所看到的,与Kohana不同,在第3页完成处理后,它会按预期继续到第2页。为什么Kohana不这样做呢?
发布于 2014-12-11 18:47:29
我已经找到了问题和解决方案。Kohana通过引用来处理ORM对象。我不知道为什么这会阻止我的foreach循环完成,但它确实停止了。
解决方案是遍历一次ORM对象,将每个页面的详细信息存储在一个stdClass数组中。这样它们就不是一个引用,所以当我把新的数组传递给我的方法时,它就起作用了。
如果其他任何人能发布一个更完整的答案来解释为什么引用对象数组会有这个问题,我将不胜感激。
发布于 2014-12-11 18:50:26
我不知道它为什么这样做,但我确实认为这个解决方案会有所帮助:
更改您的查询,使find_all成为execute(null,true);它将返回一个对象,应该可以正常工作。
如果这不是重点,变化就是这只是Kohana中的一个bug。
https://stackoverflow.com/questions/27420249
复制相似问题