ФорумПрограммирование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("<A HREF=\""."?ID=".$ID1."\">".$row["name"]."</A>"." <br>");
    ShowTree($ID1);
    }
    }

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

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

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

    а) так как у тебя написано куй ты чего выделишь, юзай буфер, а не сразу выводи данные в браузер;
    б) как понять что меню вложенное, если у тебя все выводится одинаково <a /><br /><a /><br /><a /><br /><a /><br />…;
    в) если у тебя 10 пунктов, вложенных друг в друга, будет выполнено 10 запросов, это ппц;
    г) стюдендобфускейткодингстайлнах "<A HREF=\""."?ID=".$ID1."\">".$row["name"]."</A>"." <br>", чтобниктонедогадался!
    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 'title',
    m.link AS 'link',
    m.depth AS 'depth'
    FROM
    menu_items AS m
    WHERE
    m.publish='Y'
    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="SELECTpid FROM menu";
    $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="SELECTpid FROM menu";
    $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 = "SELECT pid FROM menu";
    $result = mysql_query($sql, $db);
    $parents = array();
    while ($row = mysql_fetch_array($result))
    {
       $parents[] = $row['pid'];
    }
    var_dump($parents);
    Work, buy, consume, die
  • artoodetoo

    Сообщения: 5139 Репутация: 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="javascript">
    <!–
    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 + "." + i)) {
    el.style.display = (el.style.display == 'block')?'none':'block';
    i++;
    }
    else clearInterval(t);
    }
    –>
    </script>


    $host = "localhost";
    $namedb = "restonshop";
    $user_login = "root";
    $user_password = "root";

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

    $sql_pid = "SELECT DISTINCT pid FROM menu";
    $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['pid'];
    }

    function ShowTree($ParentID, $lvl) {

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

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

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

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

    echo("<A ".$style1." title='".$row["name"]."'>".$row["name"]./*$pref."-LVL-".$lvl.*/"</A>"." \n");
    ShowTree($ID1, $lvl);
    $lvl–;
    }
    echo("</UL>\n");
    }
    }
    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 + "." + i)) {

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

    el.style.display = (el.style.display == 'block')?'none':'block';
    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 + "=" + escape(value);
    }

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

    function getCookie(name) {
    var cookie = " " + document.cookie;
    var search = " " + name + "=";
    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(";", 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("tree_view"); // переменная существует значит присваиваем ей значение из переменной куки
    }

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

    if(el = document.getElementById(lit + "." + i)) {

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

    el.style.display = (el.style.display == 'block')?'none':'block';
    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 секунды

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

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