Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Построение многомерного массива
Форумы портала PHP.SU » » Хранение данных, их вывод и обработка » Построение многомерного массива

Страниц (1): [1]
 

1. Haron - 15 Июня, 2011 - 00:47:34 - перейти к сообщению
В общем есть у меня такая вот рекурсивная функция:

PHP:
скопировать код в буфер обмена
  1. $menu = array();
  2. function get_menu_data($cat_id = null)
  3. {
  4.         global $db;
  5.         global $menu;
  6.        
  7.         if (!$cat_id) $cat_id = 1;
  8.     $row = $db -> select(
  9.                                
  10.                                         "       SELECT mtl_id
  11.                                         FROM site_mtls_menu
  12.                                         WHERE root_id = ?", $cat_id);
  13.        
  14.         if ($row)
  15.         {
  16.                 foreach ($row as $key => $item)
  17.                 {                      
  18.                         get_menu_data($item['mtl_id']);
  19.                 }
  20.         }
  21.         else
  22.         {
  23.                 return true;
  24.         }
  25. }


Данная функция - рекурсивно обходит все записи в таблице БД, записи в таблице - представляют собой "дерево" данных, у каждого узла дерева (собственно записи в таблице) - есть два параметра (ими характеризуется узел дерева) - root_id (Id родительского материала) и mtl_id(Id материала). Сама таблица - естественно содержит всего два поля, по которым строится "дерево данных".

Так вот, в чём задача-то?
Надо каким-то образом переделать эту функцию так - чтобы она массив $menu - заполнила "древовидной" многомерной структурой, фактически - построило это самое дерево данных в виде многомерного массива.

Чтобы лучше понять задачу я изобразил это "графически": (только мне это слабо помогло):

Вот такие есть записи в базе данных:
--------------------
mtl_id root_id
--------------------
2 1
3 1
4 1
5 2
6 2
7 6

А вот что надо бы из этих записей построить:
PHP:
скопировать код в буфер обмена
  1.         # У элемента с mtl_id = 2 - есть потомки (5 и 6)
  2.         2 => array(
  3.                 5       => null,
  4.                 # mtl_id = 6 - он тоже не одинок:
  5.                 6       => array(
  6.                                 7 => null
  7.                         ),
  8.         ),
  9.         # У других - потомков нет:
  10.         3 => null,
  11.         4 => null,
  12. )
  13.  
  14. # 1 - это корень дерева, его в массиве не надо указывать.


Так как же решить задачу?
2. DeepVarvar - 15 Июня, 2011 - 01:23:05 - перейти к сообщению
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT menu.id,menu.name,sub.id,sub.name FROM menu
  2. LEFT JOIN menu sub ON (sub.parent_id = menu.id)
  3. GROUP BY menu.id,sub.id ORDER BY menu.id,sub.id

Не проверял...
(Добавление)
Вот еще тема: http://www[dot]getinfo[dot]ru/article610[dot]html
3. Haron - 15 Июня, 2011 - 02:22:24 - перейти к сообщению
DeepVarvar

Щас заюзаю твой способ, тем не менее - одно из решений проблемы найдено:
Пролог: Я конечно понимаю, что это феерический звездец в вакууме, но это первое, что пришло в голову после длительного обдумывания ситуации. Тем не менее, способ отлично выполняет свою задачу.

PHP:
скопировать код в буфер обмена
  1.  
  2. $menu = '';
  3. function get_menu_data($cat_id = null, $prefix = '')
  4. {
  5.         global $db;
  6.         global $menu;
  7.        
  8.         if (!$cat_id) $cat_id = 1;
  9.         $row = $db -> select(
  10.                                
  11.                                         '       SELECT mtl_id
  12.                                         FROM site_mtls_menu
  13.                                         WHERE root_id = ?', $cat_id);
  14.        
  15.         if ($row)
  16.         {
  17.                 foreach ($row as $key => $item)
  18.                 {                      
  19.                         $menu .= $prefix . "[{$item['mtl_id']}]" . PHP_EOL;
  20.                         get_menu_data($item['mtl_id'], $prefix . "[{$item['mtl_id']}]");
  21.                 }
  22.         }
  23.         else
  24.         {
  25.                 return $menu;
  26.         }
  27. }
  28.  
  29. get_menu_data(1, '$var[1]');
  30. $test = '<?PHP ' . PHP_EOL . str_replace(PHP_EOL, " = '';" . PHP_EOL, $menu);
  31.  
  32. $handle = fopen('c:\test.php', 'w+');
  33. if (fwrite($handle, $test))
  34. {
  35.         fclose($handle);
  36.         require_once('c:\test.php');
  37.         print_r($var);
  38. }
  39.  


Мде...
4. EuGen - 15 Июня, 2011 - 09:12:09 - перейти к сообщению
Haron пишет:
require_once('c:\test.php');

Тогда уж http://php.su/functions/?parse_str или http://php.su/functions/?eval на крайний случай.
А по-хорошему если структура столь проста, сколь Вы ее описали, то для меню достаточно двумерного массива, а не многомерного. И запросов к БД рекурсивных удастся избежать. Вот здесь об этом есть обсуждение: http://forum.php.su/topic.php?fo...1&topic=7326
5. Haron - 15 Июня, 2011 - 10:39:01 - перейти к сообщению
Да, с eval()'ом проще вышло гораздо. А нужна была именно многомерная структура, так как предполагается что меню может быть неограниченного уровня вложенности, а двумерное - это как частный случай. Ну прямо как в той теме - задачка оказывается. Я и забыл про неё, тут тем много очень. Вообще, запись файла помедленней но побезопасней чем eval(). eval() у меня отключен в php.ini

Вообще, решение вопроса - думаю оригинальное и имеет право на жизнь Улыбка
6. Slavenin - 15 Июня, 2011 - 10:52:46 - перейти к сообщению
древовидная структура бд безнадежно устарела и имеет кучу недостатков http://www[dot]intuit[dot]ru/department/[dot][dot][dot]e/dbmdi/3/1[dot]html . Мой вам совет, пользуйтесь современными способами организации данных http://www[dot]intuit[dot]ru/department/[dot][dot][dot]atabase/dbmdi/4/

 

Powered by ExBB FM 1.0 RC1