foreach — php yalinqo — перебрать результат

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

введите описание изображения здесь

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

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

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

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

1-СУМКИ (3,4,) …

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

Это то, что есть какой-то скрытый курсор, который создает проблему?
Или что-то не так в формировании запроса 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 ')  ... ';
}
}

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

2

Решение

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

Ваш код более сложный, где он не нужен, и недостаточно сложный, где это необходимо. 🙂

  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] =>
)
)
)
)
3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]