Использование массива вместо большого количества запросов к базе данных в PHP - PullRequest
2 голосов
/ 22 ноября 2011

Моя функция выглядит так. Это работает, но выполняет много работы (рекурсивно вызывает себя и выполняет много запросов к базе данных). Должен быть другой способ сделать то же самое, но с массивом (с одним запросом). Я не могу понять, как изменить эту функцию, чтобы она работала с массивом.

function genMenu($parent, $level, $menu, $utype) {
    global $db;
    $stmt=$db->prepare("select id, name FROM navigation WHERE parent = ? AND menu=? AND user_type=?") or die($db->error);
    $stmt->bind_param("iii", $parent, $menu, $utype) or die($stmt->error);
    $stmt->execute() or die($stmt->error);

    $stmt->store_result();
    /* bind variables to prepared statement */
$stmt->bind_result($id, $name) or die($stmt->error);
    if ($level > 0 && $stmt->num_rows > 0) {
        echo "\n<ul>\n";
    }
    while ($stmt->fetch()) {
        echo "<li>";
        echo '<a href="?page=' . $id . '">' . $name . '</a>';
        //display this level's children
        genMenu($id, $level+1, $menu, $utype);
        echo "</li>\n\n";
    }
    if ($level > 0 && $stmt->num_rows > 0) {
        echo "</ul>\n";
    }
    $stmt->close();
}

Ответы [ 4 ]

2 голосов
/ 22 ноября 2011

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

$tree = array();
$sql = "SELECT id, parent, name FROM menu WHERE parent ... etc.... ";
$results = mysql_query($sql) or die(mysql_error());
while(list($id, $parent, $name) = mysql_fetch_assoc($results)) {
    $tree[$id] = array('name' => $name, 'children' => array(), 'parent' => $parent);
    if (!array_key_exists($tree[$parent]['children'][$id])) {
        $tree[$parent]['children'][$id] = $id;
    }
}

Для этого япредполагая, что ваше дерево имеет узел верхнего уровня '0'.если нет, то вам придется немного подкорректировать.

Это даст вам двойную древовидную структуру.Каждый узел в дереве имеет список своих дочерних элементов в подмассиве ['children'], и каждый узел в дереве также указывает на своего родителя через атрибут ['parent'].

Учитывая определенный начальный узел, вы можете пройти вверх по дереву следующим образом:

$cur_node = 57; // random number
$path = array();
do {
    $parent = $tree[$cur_node]['parent'];
    $path[] = $parent;
    $cur_node = $parent;
} while ($parent != 0);
1 голос
/ 22 ноября 2011

Может быть, не то, что вы хотели, но замечательно, когда речь идет о деревьях .Вам нужно будет перестроить вашу таблицу и иметь некоторый код для вывода html, но у вас будет только один запрос.Это может стоить усилий в долгосрочной перспективе.

т.е.. Если у вас есть это меню

# Menu hierarchy:
 - Home
 - Product
    |- Tv
    |- Radio
 - About us   

В БД оно будет выглядеть так:

+----+----------+-----------+-----+-----+
| id | menu     | parent_id | lft | rgt |
+----+----------+-----------+-----+-----+
| 1  | Home     | null      | 1   | 2   |
+----+----------+-----------+-----+-----+
| 2  | Product  | null      | 3   | 8   |
+----+----------+-----------+-----+-----+
| 3  | Tv       | 2         | 4   | 5   |
+----+----------+-----------+-----+-----+
| 4  | Radio    | 2         | 6   | 7   |
+----+----------+-----------+-----+-----+
| 5  | About us | null      | 9   | 10  |
+----+----------+-----------+-----+-----+

Данные могут быть получены с использованием аналогичного запроса

$select = "SELECT * FROM table_name WHERE lft BETWEEN 3 AND 8;"

Чтобы вывести определенное меню:

 - Product
    |- Tv
    |- Radio

Я знаю, что это не совсем тот ответ, который вы искали, но, к вашему сведению, существуют другие способы использования данных иерархического дерева.*

Удачи.

1 голос
/ 22 ноября 2011

Я думаю, что первое, что вы можете исправить, это удалить WHERE parent =? и затем работать с результирующим результатом запроса, это заставит вас немного больше работать с ним, но определенно защитит ваши операции ввода-вывода.

Использование частей раствора Marc B

$tree = array();
$sql = "select id, parent, name FROM navigation AND menu=? AND user_type=?";
$results = mysql_query($sql) or die(mysql_error());
while(list($id, $parent, $name) = mysql_fetch_assoc($results)) {
    $tree[$id] = array('name' => $name, 'children' => array(), 'parent' => $parent);
    if (!array_key_exists($tree[$parent]['children'][$id])) {
        $tree[$parent]['children'][$id] = $id;
    }
}

print_r($tree);

Заменить? с фактическими значениями, и дать этому пробежку, каков ваш вывод?

0 голосов
/ 22 ноября 2011

В прошлом я писал некрасиво, но с помощью простого SELECT:

Я сохраняю в текстовых / полевых строках строки вроде этого:

/001
/001/001
/001/002
/002
/002/001
/002/001/001

Игнорируем иврит и смотрим в окно.Массив сообщений, чтобы посмотреть, как он работает: http://www.inn.co.il/Forum/Forum.aspx/t394009#4715854

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...