ФорумПрограммированиеPHP для идиотов → PHP, рекурсия, дерево

PHP, рекурсия, дерево

  • smv

    Сообщения: 236 Репутация: N Группа: Кто попало

    Spritz 17 марта 2010 г. 10:51

    Добрый вечер! Как мне в коде приведенном ниже, который рекурсивно извлекает пункты меню, отследить чьих-нибудь "родителей" и выделить их например цветом? Как такую проверку сделать?


    include ("connect_bd.php");
    function ShowTree($ParentID) {

    global $db;

    $sSQL="SELECT id,name,pid FROM menu WHERE pid=".$ParentID."";
    $result=mysql_query($sSQL, $db);

    if (mysql_num_rows($result) > 0) {

    while ( $row = mysql_fetch_array($result) ) {
    $ID1 = $row["id"];
    echo(&quot;<A HREF=\&quot;&quot;.&quot;?ID=&quot;.$ID1.&quot;\&quot;>&quot;.$row[&quot;name&quot;].&quot;</A>&quot;.&quot; <br>&quot;);
    ShowTree($ID1);
    }
    }

    }
    ShowTree(0);
    mysql_close($db);
  • Nyaah

    Сообщения: 574 Репутация: N Группа: Джедаи

    Spritz 17 марта 2010 г. 11:08, спустя 16 минут 47 секунд

    а) так как у тебя написано куй ты чего выделишь, юзай буфер, а не сразу выводи данные в браузер;
    б) как понять что меню вложенное, если у тебя все выводится одинаково &lt;a />&lt;br />&lt;a />&lt;br />&lt;a />&lt;br />&lt;a />&lt;br />…;
    в) если у тебя 10 пунктов, вложенных друг в друга, будет выполнено 10 запросов, это ппц;
    г) стюдендобфускейткодингстайлнах &quot;&lt;A HREF=\&quot;&quot;.&quot;?ID=&quot;.$ID1.&quot;\&quot;>&quot;.$row[&quot;name&quot;].&quot;&lt;/A>&quot;.&quot; &lt;br>&quot;, чтобниктонедогадался!
    Work, buy, consume, die
  • smv

    Сообщения: 236 Репутация: N Группа: Кто попало

    Spritz 17 марта 2010 г. 13:57, спустя 2 часа 48 минут 44 секунды

    так ладно… Тогда подскажите направление в котором двигаться… От программистов (уж не знаю как оценить их квалификацию) слышал что строить деревья правильнее с помощью рекурсивной функции… Стоит придерживаться такого совета?
  • Nyaah

    Сообщения: 574 Репутация: N Группа: Джедаи

    Spritz 17 марта 2010 г. 14:13, спустя 16 минут 18 секунд

    если уверен, что у тя циклов нет, то строй рекурсивно, если нет, то не стоит =)
    я выборку делаю сразу всю, но у меня обычно деревья в базе лежат в двух таблицых, собственно данные и таблица отношений node-ancestor, плюс храню глобальную сортировку, поэтому выборка у меня выглядит примерно так:
    SELECT
    m.title AS &#39;title&#39;,
    m.link AS &#39;link&#39;,
    m.depth AS &#39;depth&#39;
    FROM
    menu_items AS m
    WHERE
    m.publish=&#39;Y&#39;
    ORDER BY
    m.global_ordering;

    После чего остаётся только вывести все это дело. Но при таком подходе в админке нужно весьма аккуратно реализовать добавление/удаление/перемещение пунктов меню, зато с выводом проблем нет.
    Work, buy, consume, die
  • smv

    Сообщения: 236 Репутация: N Группа: Кто попало

    Spritz 17 марта 2010 г. 17:02, спустя 2 часа 49 минут 8 секунд

    Вопрос не совсем по теме, но все-таки для построения дерева меня интерисует.

    Есть у меня таблица в БД:

    id | pid | name
    1 | 0 | Раздел 1
    2 | 1 | Раздел 1.1
    3 | 0 | Раздел 2
    4 | 3 | Раздел 2.1
    5 | 4 | Раздел 2.1.1
    6 | 4 | Раздел 2.1.2
    7 | 1 | Раздел 1.2
    8 | 1 | Раздел 1.3

    Для определения какой пункт меню может быть чьим-либо родителем придумал сделать так:

    Нужно составить след. условие. - Если значение какого-либо id присутствует в массиве значений pid, то этут пункт меню является родителем.

    Шаг следующий. Надо все это реализовать. В этом вопросе и понадобится мне ваша помощь.

    Код следующий:

    $select_pid_arr=&quot;SELECTpid FROM menu&quot;;
    $result_pid_arr=mysql_query($select_pid_arr, $db);

    while ($row_pid_arr = mysql_fetch_array($result_pid_arr) ) {

    А вот тут загвоздка. Каким образом возможно скинуть все имеющиеся выбранные значения pid в массив, так чтобы применить его в не цыкла While? Хочу сделать именно так потому что проверка родитель пункт меню или нет, у меня будет проходить в рекурсивной функции. И каждый раз выполнять мне этот запрос не хочется.

    }




    {+++67+++} Вопрос не совсем по теме, но все-таки для построения дерева меня интерисует.

    Есть у меня таблица в БД:

    id | pid | name
    1 | 0 | Раздел 1
    2 | 1 | Раздел 1.1
    3 | 0 | Раздел 2
    4 | 3 | Раздел 2.1
    5 | 4 | Раздел 2.1.1
    6 | 4 | Раздел 2.1.2
    7 | 1 | Раздел 1.2
    8 | 1 | Раздел 1.3

    Для определения какой пункт меню может быть чьим-либо родителем придумал сделать так:

    Нужно составить след. условие. - Если значение какого-либо id присутствует в массиве значений pid, то этут пункт меню является родителем.

    Шаг следующий. Надо все это реализовать. В этом вопросе и понадобится мне ваша помощь.

    Код следующий:

    $select_pid_arr=&quot;SELECTpid FROM menu&quot;;
    $result_pid_arr=mysql_query($select_pid_arr, $db);

    while ($row_pid_arr = mysql_fetch_array($result_pid_arr) ) {

    А вот тут загвоздка. Каким образом возможно скинуть все имеющиеся выбранные значения pid в массив, так чтобы применить его в не цыкла While? Хочу сделать именно так потому что проверка родитель пункт меню или нет, у меня будет проходить в рекурсивной функции. И каждый раз выполнять мне этот запрос не хочется.

    }
  • Nyaah

    Сообщения: 574 Репутация: N Группа: Джедаи

    Spritz 18 марта 2010 г. 2:18, спустя 9 часов 15 минут 59 секунд

    Убейте меня…
    $sql = &quot;SELECT pid FROM menu&quot;;
    $result = mysql_query($sql, $db);
    $parents = array();
    while ($row = mysql_fetch_array($result))
    {
       $parents[] = $row[&#39;pid&#39;];
    }
    var_dump($parents);
    Work, buy, consume, die
  • artoodetoo

    Сообщения: 5138 Репутация: N Группа: в ухо

    Spritz 18 марта 2010 г. 3:13, спустя 54 минуты 34 секунды

    smv, бля, ну буквально вчера была ссылка про всю фигню

    если внутреннее представление дерева в PHP - массив, то все просто. рекурсия может понадобиться для поиска. а чтобы взять целиком поддерево, достаточно просто скопировать элемент массива

    http://phpclub.ru/faq/Tree/Internal?v=38y
    ιιlllιlllι унц-унц
  • smv

    Сообщения: 236 Репутация: N Группа: Кто попало

    Spritz 20 марта 2010 г. 6:59, спустя 2 дня 3 часа 46 минут

    Вот сделал дерево.. конечно доработать немного надо наверное.. но все - таки работает.. Может пригодится кому-нибудь

    <script language=&quot;javascript&quot;>
    <!–
    var t,lit,i;
    function tree(liter) {
    lit=liter;//литера
    i=1;//счетчик
    t = setInterval(show, 2); //развертываем/сворачиваем с заданным интервалом
    //t = show();
    }
    function show() {
    var el;
    if(el = document.getElementById(lit + &quot;.&quot; + i)) {
    el.style.display = (el.style.display == &#39;block&#39;)?&#39;none&#39;:&#39;block&#39;;
    i++;
    }
    else clearInterval(t);
    }
    –>
    </script>


    $host = &quot;localhost&quot;;
    $namedb = &quot;restonshop&quot;;
    $user_login = &quot;root&quot;;
    $user_password = &quot;root&quot;;

    $db = mysql_connect($host, $user_login, $user_password) or die(mysql_error());
    mysql_select_db($namedb, $db) or die(mysql_error());
    @mysql_query (&quot;SET NAMES `cp1251`&quot;);

    $sql_pid = &quot;SELECT DISTINCT pid FROM menu&quot;;
    $result_sql_pid = mysql_query($sql_pid, $db);
    $pid_arr = array();
    while ($row_result_sql_pid = mysql_fetch_array($result_sql_pid))
    {
    $pid_arr[] = $row_result_sql_pid[&#39;pid&#39;];
    }

    function ShowTree($ParentID, $lvl) {

    global $db;
    global $lvl;
    global $pid_arr;
    $lvl++;

    $sSQL=&quot;SELECT id,name,pid FROM menu WHERE pid=&quot;.$ParentID.&quot;&quot;;
    $result=mysql_query($sSQL, $db);

    if (mysql_num_rows($result) > 0) {
    echo(&quot;<UL>\n&quot;);
    while ( $row = mysql_fetch_array($result) ) {
    $ID1 = $row[&quot;id&quot;];
    $i++;
    if (in_array($ID1, $pid_arr)){
    $pref = &quot;-PARENT&quot;;
    $style1 = &quot;onclick=\&quot;tree(&#39;&quot;.$ID1.&quot;&#39;)\&quot;&quot;;
    }
    if (!in_array($ID1, $pid_arr) || $lvl >= 2){
    $style2 = &quot;id=&#39;&quot;.$row[&#39;pid&#39;].&quot;.&quot;.$i.&quot;&#39; style=&#39;display: none&#39;;&quot;;
    }

    echo(&quot;<LI &quot;.$style2.&quot;>\n&quot;);

    echo(&quot;<A &quot;.$style1.&quot; title=&#39;&quot;.$row[&quot;name&quot;].&quot;&#39;>&quot;.$row[&quot;name&quot;]./*$pref.&quot;-LVL-&quot;.$lvl.*/&quot;</A>&quot;.&quot; \n&quot;);
    ShowTree($ID1, $lvl);
    $lvl–;
    }
    echo(&quot;</UL>\n&quot;);
    }
    }
    ShowTree(0, 0);
  • smv

    Сообщения: 236 Репутация: N Группа: Кто попало

    Spritz 22 марта 2010 г. 17:06, спустя 2 дня 10 часов 7 минут

    Встал вопрос сделать так что при обновлении дерева (последний приведенный код) дерево не сворачиволось. Сымсл я понял что в куик надо занести последний развернутый элемент. С куками тоже разобрался.. Подскажите пожалуйста какое значение в куки заносить надо. Думал что надо заносить значение переменной i в функции show() но что то не получается.
  • NRG

    Сообщения: 4761 Репутация: N Группа: в ухо

    Spritz 22 марта 2010 г. 17:11, спустя 5 минут 4 секунды


    но что то не получается.
    что именно не получается ?
  • smv

    Сообщения: 236 Репутация: N Группа: Кто попало

    Spritz 22 марта 2010 г. 17:18, спустя 7 минут 36 секунд

    <!–
    var t,lit,i;
    function tree(liter) {
    lit=liter;//литера

    А вот тут вместо i=1 мы пишем условие есть ли значение в переменной куки на тот случай если мы открываем страничцу в первый раз.. и если есть переменную i приравниваем значению переменной куки.. а если переменная куки пуста то переменной i даем значение 1.

    i=1;//счетчик


    t = setInterval(show, 2); //развертываем/сворачиваем с заданным интервалом
    }
    function show() {
    var el;
    if(el = document.getElementById(lit + &quot;.&quot; + i)) {

    Вот тут я так понимаю надо вызывать функция на запись пременной i в куки.

    el.style.display = (el.style.display == &#39;block&#39;)?&#39;none&#39;:&#39;block&#39;;
    i++;
    }
    else clearInterval(t);
    }
    –>


    Правильго?
  • NRG

    Сообщения: 4761 Репутация: N Группа: в ухо

    Spritz 22 марта 2010 г. 17:23, спустя 4 минуты 35 секунд

    ну так что неясно ?
    как работать с куками в джаваскрипте?
    я бы впервую очередь заглянул бы сюда cookies javascript
  • smv

    Сообщения: 236 Репутация: N Группа: Кто попало

    Spritz 22 марта 2010 г. 17:44, спустя 20 минут 36 секунд

    Получилось вот так

    <!–

    // Функция для записи переменной в куки

    function setCookie (name, value) {
    document.cookie = name + &quot;=&quot; + escape(value);
    }

    // Функция для чтения переменной из куки

    function getCookie(name) {
    var cookie = &quot; &quot; + document.cookie;
    var search = &quot; &quot; + name + &quot;=&quot;;
    var setStr = null;
    var offset = 0;
    var end = 0;
    if (cookie.length > 0) {
    offset = cookie.indexOf(search);
    if (offset != -1) {
    offset += search.length;
    end = cookie.indexOf(&quot;;&quot;, offset)
    if (end == -1) {
    end = cookie.length;
    }
    setStr = unescape(cookie.substring(offset, end));
    }
    }
    return(setStr);
    }


    var t,lit, i;
    function tree(liter) {
    lit=liter;//литера

    if(i == undefined){ // Определяем существует ли переменная i
    i=1;//счетчик // Переменная не существует значит присваиваем ей значение 1
    }
    else
    {
    i = getCookie(&quot;tree_view&quot;); // переменная существует значит присваиваем ей значение из переменной куки
    }

    t = setInterval(show, 5); // развертываем/сворачиваем с заданным интервалом
    }
    function show() {
    var el;

    if(el = document.getElementById(lit + &quot;.&quot; + i)) {

    setCookie(&quot;tree_view&quot;, i); // Записываем значение переемнной i в куки

    el.style.display = (el.style.display == &#39;block&#39;)?&#39;none&#39;:&#39;block&#39;;
    i++;
    }
    else clearInterval(t);
    }
    –>


    И вот почемуйто дерево неоткрывается вообще {+++69+++} ой точнее открывеется но только какая то одна ветка {+++34+++} После оьновление страницы опять можновыбрать другуб ветку для открытия но следующая не открывается
  • NRG

    Сообщения: 4761 Репутация: N Группа: в ухо

    Spritz 22 марта 2010 г. 18:23, спустя 39 минут 20 секунд

    дебаж свой код.
    про alert() слышал ?
    есть кончно более гуманней console.log()

    в любом случае дебаг,дебаг и еще раз дебаг
  • smv

    Сообщения: 236 Репутация: N Группа: Кто попало

    Spritz 22 марта 2010 г. 18:29, спустя 6 минут 2 секунды

    ну а так на первый взгляд какие нибудь ошибки видиш?

Пожалуйста, авторизуйтесь, чтобы написать комментарий!