2016-03-28 3 views
2

У меня есть структура таблицы, как показано ниже, где item_id -> 1,2 являются главными пунктами меню ... и item_id -> 3,4 являются подпунктами к 1, которые могут быть определены parent_idphp yalinqo - итерация результата

enter image description here

и я использую следующий код для извлечения и перебирать этот результат. и правильно структурировать меню в пользовательском интерфейсе.

Пока я не использую цикл foreach 'foreach-1', все работает нормально. и результат

1-СУМКИ() ... 2-АКСЕССУАРЫ() ...

Но когда я добавить цикл Еогеасп 'Еогеасп-2'. Результат не показывает (2-аксессуары), как показано ниже

1-МЕШКОВ (3,4,) ...

И, как вы видите, я использую библиотеку yalinqo для выборка данных из набора результатов. И очень мало помогает на yalinqo на www.

Это что-то скрытое curser, создающее проблему? Или что-то не так в том, как формируется запрос yalinqo?

Если вы работали над yalinqo, пожалуйста, помогите мне здесь. Потому что я больше являюсь пользователем .net и имею очень мало опыта работы с php.

Я отправляю только частичный код здесь:

use \YaLinqo\Enumerable as E; 

... 

if ($connection) 
    { 
     $result = mysqli_query($connection, "CALL fetch_main_menu") or die("Query fail: " . mysqli_error()); 

     $result_data = E::from ($result) ; 

     $top_menu = E::from ($result_data) 
     ->where (function($item){return $item["parent_id"]==null;}) 
     ->select (function ($item){return $item;}); 

     //foreach - 1 
     foreach ($top_menu as $i) 
     { 
      $item_id = $i["id"]; 
      $item_name = $i["name"]; 

      echo $item_id . '-' . $item_name ; 

      //fetch subitems 
      $sub_menu = E::from ($result_data) 
      ->where (function($item){global $item_id; return $item["parent_id"] != null && $item["parent_id"] == $item_id;}) 
      ->select (function ($item){return $item;}); 

      echo '('; 

      //foreach - 2 
      foreach($sub_menu as $sub_i) 
      { 
       echo $sub_i["id"] . ','; 
      } 

      unset($sub_menu); 

      echo ') ... '; 
     } 
    } 

P.S .: я был бы рад использовать еще более эффективную работу вокруг, если есть для структурирования панели меню.

+0

Вы можете использовать базу данных NoSQL например, mongoDB и сохранить дерево в базе данных. Или используйте postgrySql для вставки массива для родительских полей. Или используйте графическую базу данных. Или mysql great 5.7 и используйте формат json. и многое другое и т. д., но вы можете выбрать один запрос для всех данных и один интерзатор foreach. – Naumov

ответ

3

Если у вас есть какие-либо вопросы с YaLinqo, пожалуйста, не стесняйтесь спрашивать меня напрямую или создать вопрос поддержки в YaLinqo's issue tracker.

Ваш код более сложный, где это необходимо, и при необходимости не достаточно сложно. :)

  1. select (function ($item){return $item;}) ненужно, он ничего не делает, просто where достаточно (то же самое относится и к .NET LINQ, если вы используете функциональный синтаксис):

    $top_menu = E::from ($result_data) 
        ->where (function($item){return $item["parent_id"]==null;}); 
    
  2. Вместо использования global вы можете добавить use заявление ваших анонимных функций:

    $sub_menu = E::from ($result_data) 
        ->where (function($item) use($item_id) { 
         return $item["parent_id"] != null && $item["parent_id"] == $item_id; 
        }); 
    

    в отличие от .NET, переменные должны быть захвачены в явном виде. Кроме того, в новом коде следует избегать global.

  3. Ваша модель предлагает использовать рекурсивные функции, но ваш код поддерживает только 2 уровня. Если вам нужно всего два уровня, это легко сделать с одним запросом.

Давайте предположим, что у нас уже есть массив:

$items = [ 
    [ 'id' => 1, 'name' => "BAGS", 'parent_id' => null ], 
    [ 'id' => 2, 'name' => "ACCESSORIES", 'parent_id' => null ], 
    [ 'id' => 3, 'name' => "Messenger", 'parent_id' => 1 ], 
    [ 'id' => 4, 'name' => "Sling", 'parent_id' => 1 ], 
    [ 'id' => 5, 'name' => "Earrings", 'parent_id' => 2 ], 
    [ 'id' => 6, 'name' => "Clip", 'parent_id' => 2 ], 
]; 

Построение иерархии меню может быть сделано таким образом:

$menu = from($items) 
    ->where(function ($ti) { 
     return $ti['parent_id'] === null; 
    }) 
    ->select(function ($ti) use ($items) { 
     return [ 
      'menu' => $ti, 
      'items' => from($items) 
       ->where(function ($si) use ($ti) { 
        return $si['parent_id'] === $ti['id']; 
       }) 
     ]; 
    }); 

print_r($menu->toArrayDeep()); 

Выход:

Array 
(
    [0] => Array 
     (
      [menu] => Array 
       (
        [id] => 1 
        [name] => BAGS 
        [parent_id] => 
       ) 
      [items] => Array 
       (
        [2] => Array 
         (
          [id] => 3 
          [name] => Messenger 
          [parent_id] => 1 
         ) 
        [3] => Array 
         (
          [id] => 4 
          [name] => Sling 
          [parent_id] => 1 
         ) 
       ) 
     ) 
    [1] => Array 
     (
      [menu] => Array 
       (
        [id] => 2 
        [name] => ACCESSORIES 
        [parent_id] => 
       ) 
      [items] => Array 
       (
        [4] => Array 
         (
          [id] => 5 
          [name] => Earrings 
          [parent_id] => 2 
         ) 
        [5] => Array 
         (
          [id] => 6 
          [name] => Clip 
          [parent_id] => 2 
         ) 
       ) 
     ) 
) 

Или, если все, что вам нужно, это строка:

$menustring = from($items) 
    ->where(function ($ti) { 
     return $ti['parent_id'] === null; 
    }) 
    ->select(function ($ti) use ($items) { 
     return "{$ti['id']}-{$ti['name']}(" 
     . from($items) 
      ->where(function ($si) use ($ti) { 
       return $si['parent_id'] === $ti['id']; 
      }) 
      ->toString(',', function ($si) { 
       return "{$si['id']}-{$si['name']}"; 
      }) 
     . ")"; 
    }) 
    ->toString(';'); 

echo($menustring); 

Выход:

1-BAGS(3-Messenger,4-Sling);2-ACCESSORIES(5-Earrings,6-Clip) 

И, наконец, рекурсивная функция, которая работает с любым уровнем вложенности:

function get_menu_with_subitems ($items, $item) 
{ 
    $subitems = from($items) 
     ->where(function ($i) use ($item) { 
      return $i['parent_id'] === $item['id']; 
     }) 
     ->select(function ($i) use ($items) { 
      return get_menu_with_subitems($items, $i); 
     }) 
     ->toList(); 
    return [ 
     'id' => $item['id'], 
     'name' => $item['name'], 
     'items' => count($subitems) > 0 ? $subitems : null, 
    ]; 
} 

$root = [ 'id' => null, 'name' => 'Root' ]; 
$menu = get_menu_with_subitems($items, $root)['items']; 
print_r($menu); 

Выход:

(
    [0] => Array 
     (
      [id] => 1 
      [name] => BAGS 
      [items] => Array 
       (
        [0] => Array 
         (
          [id] => 3 
          [name] => Messenger 
          [items] => 
         ) 
        [1] => Array 
         (
          [id] => 4 
          [name] => Sling 
          [items] => 
         ) 
       ) 
     ) 
    [1] => Array 
     (
      [id] => 2 
      [name] => ACCESSORIES 
      [items] => Array 
       (
        [0] => Array 
         (
          [id] => 5 
          [name] => Earrings 
          [items] => 
         ) 
        [1] => Array 
         (
          [id] => 6 
          [name] => Clip 
          [items] => 
         ) 
       ) 
     ) 
) 
Смежные вопросы