2014-12-11 5 views
0

Я использую Kohana 3.3 и пытаюсь вывести страницы в меню и все подменю. Подменю хранятся в той же таблице, что и страницы, называемые страницами. Единственное различие между страницей и подменю - это флаг. Это таблица структуры страницы и примеры страниц, которые я создал, чтобы получить эту работу.Kohana несколько циклов объектов ORM foreach заканчиваются раньше

| 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 

Таким образом, после второго вызова метода меню для подменю (ID 3), цикл Еогеасп завершает ID 3, но не продолжить на следующий стр. Я не понимаю, почему? Я уже делал петли foreach, подобные этим в прошлом, которые работали, это мой первый раз, когда я делаю это в Кохане, хотя так думаю, что это то, о чем говорил Кохана, что я не понимаю.

Я создал eval.in of this, показывая, что работает код, и что это должно быть что-то в Кохане. Это результат всех эха от 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 

Как вы можете видеть, в отличие от Кохана, после того, как страница 3 заканчивается обработка продолжает на странице 2, как и ожидалось. Почему Кохана не делает этого?

ответ

0

Я нашел проблему и решение. Kohana обрабатывает объекты ORM по ссылке. Я не знаю, почему это останавливает мой цикл foreach, но это так.

Решение состояло в том, чтобы прокручивать объекты ORM один раз, сохраняя детали каждой страницы в массиве stdClass'а. Таким образом, они не были ссылкой, поэтому, когда я передал новый массив в свой метод, он работал.

Если кто-то может опубликовать более полный ответ, объясняющий почему массив ссылочных объектов имеет эту проблему, я ценю это.

0

Я не знаю, почему он это делает, но я думаю, что это решение поможет:

Изменить запрос, сделать find_all выполнить (нуль, правда); он вернет объект и должен просто работать.

Если это не так, изменения - это всего лишь ошибка в Кохане.

+0

Модель не имеет метода 'execute', поэтому я не могу этого сделать. – Styphon

+0

Его стандартная функция Kohana :: ORM, если я не ошибаюсь. – Chilion

+0

Ну, когда я попробовал, он сказал, что его не существует. Это также [не указано в api] (http://kohanaframework.org/3.3/guide-api/ORM). – Styphon

Смежные вопросы