Создать дерево с рекурсивным массивом, объединяющим данные из двух таблиц

0

Мне нужно сгенерировать дерево из двух таблиц MySQL в PHP и напечатать его с помощью HTML. Моя основная проблема заключается в том, что у меня есть две таблицы, где можно получить данные. Одна таблица - страницы и другие переводы, потому что у меня есть 3 языка на веб-сайте, и все переводы остаются в таблице переводов.

Схема этих таблиц:

страницы

id INT
id_user INT
id_parent INT
order INT
template INT
image VARCHAR
flag_active INT
flag_extra INT
edited INT
created INT

переводы

id INT
id_user INT
locale VARCHAR
module VARCHAR
pk INT
label VARCHAR
value TEXT
edited INT

Когда я добавляю страницу я значения title, slug and text страниц (не на схеме, потому что они зависят от языкового стандарта) в переводах:

INSERT INTO pages (id_user, template, image, flag_active, flag_extra, edited, created)
VALUES (1, 0, 'test.jpg', 1, 1, 12345, 12345)

<!-- the pages.id is 4, for example, for next insert: -->

INSERT INTO translations (id_user, locale, module, pk, label, value, edited)
VALUES (1, 'en', 'pages', 4, 'title', 'This is the title in English', 12345)

INSERT INTO translations (id_user, locale, module, pk, label, value, edited)
VALUES (1, 'en', 'pages', 4, 'slug', 'this-is-the-title-in-english', 12345)

INSERT INTO translations (id_user, locale, module, pk, label, value, edited)
VALUES (1, 'en', 'pages', 4, 'text', 'This is the text in English', 12345)

INSERT INTO translations (id_user, locale, module, pk, label, value, edited)
VALUES (1, 'es', 'pages', 4, 'title', 'Este es el titulo en Español', 12345)

INSERT INTO translations (id_user, locale, module, pk, label, value, edited)
VALUES (1, 'es', 'pages', 4, 'slug', 'este-es-el-titulo-en-espanol', 12345)

INSERT INTO translations (id_user, locale, module, pk, label, value, edited)
VALUES (1, 'es', 'pages', 4, 'text', 'Este es el contenido en Español', 12345)

И затем, когда я получаю доступ к странице на определенном языке, сначала в PHP я выбираю страницу из таблицы pages, а затем заглядываю в translations для: WHERE module='pages' AND pk='4' AND locale='en' и получаю всю информацию Мне нужно со страницы и переведенных значений текста.

Я объяснил, как работает моя система перевода. Теперь у меня проблема в backend (и frontend), потому что мне нужно построить дерево с этих страниц на одном языке. Моя идея - бросить рекурсивный массив, но я не знаю, как объединить данные, потому что я думаю, что это будет вещь PHP, а не MySQL.

Я не создал функцию дерева, и мне кажется, что мне нужны функции дерева, потому что:

  • Мне нужно генерировать и массивы из запросов MySQL, объединяя данные страницы и перевод.
  • Мне нужно создать список <ol /> в HTML с вложенным деревом.

Для первого первого массива деревьев, MySQL, мне нужно сделать запись MySQL для EACH? Или это может быть сделано только с одним запросом MySQL? Пример кода, не проверенный и написанный напрямую:

function mysql_tree($parent_id = 0)
{
    $return = array();

    $query = "SELECT * FROM pages WHERE id_parent=$parent_id";

    $result = mysql_query($query);

    if(mysql_num_rows($result) != 0)
    {
        $i = 0;

        while($row = mysql_fetch_array($result))
        {
            $return[$i] = array(
                'id' => $row["id"];
                //etc
            );

            // Time to merge the data for each page from translations????

            $return[$i]["childs"] = mysql_tree($row["id"]);

            $i++;
        }
    }

    return $return;
}

Для второй функции дерева я предполагаю, что что-то похожее на MySQL?

Заранее благодарю вас!

UPDATE: пример вложенного списка, запрошенный Vincent

Array(
    [0] => Array(
        [id] => 4
        [id_user] => 1
        [id_parent] => 0
        [order] => 0
        [template] => 1
        [image] => NULL
        [flag_active] => 1
        [flag_extra] => 0
        [edited] => 12345
        [created] => 12345
        [title] => This is the title in English
        [slug] => this-is-the-slug-in-english
        [childs] => Array(
            [0] => Array(
                [id] => 5
                [id_user] => 1
                [id_parent] => 4
                [order] => 0
                [template] => 1
                [image] => NULL
                [flag_active] => 1
                [flag_extra] => 0
                [edited] => 12345
                [created] => 12345
                [title] => This is the title in English 2
                [slug] => this-is-the-slug-in-english-2
                [childs] => NULL
            )
        )
    )
)

И дерево HTML:

<ol>
    <li class="id_4"><a href="/pages/this-is-the-slug-in-english">This is the title in English</a>
        <ol>
            <li class="id_5"><a href="/pages/this-is-the-slug-in-english-2">This is the title in English 2</a></li>
        </ol>
    </li>
</ol>
  • 0
    Мммм .... что?
  • 0
    @Tomalak: Томалак: ха-ха, я пытался объяснить все это, потому что люди обычно говорят, что я плохо описываю и отвечаю. Резюме: у меня есть две таблицы для вложенного дерева, которые не могут быть объединены в MySQL, потому что он использует другую процедуру для хранения языков, и я хочу знать, как создать дерево с меньшим количеством возможных запросов MySQL.
Показать ещё 2 комментария
Теги:

2 ответа

1
Лучший ответ

Я, наконец, решил это, используя необходимые MySQL-запросы. Я отправляю код, потому что может быть полезен для другого пользователя. Я использую CodeIgniter, но он будет работать с обычным mysql_query().

PS: Обратите внимание, что я использую испанские имена, а также легко понять.

public function tree($id_padre = 0, $locale = null)
{
    $return = array();

    if(false == is_numeric($id_padre))
        return $return;

    if(null == $locale)
        return $return;

    $query = $this->db->where("id_padre", $id_padre)->get("paginas");

    if($query->num_rows() > 0)
    {
        $i = 0;

        foreach($query->result_array() as $row)
        {
            $translation = (array) $this->get($row["id"], $locale); // This returns the "title", "slug" and "text" from the translations tables

            $data["id"] = $row["id"];
            $data["id_padre"] = $row["id_padre"];
            $data["orden"] = $row["orden"];

            $data = array_merge($data, $translation);

            $data["childs"] = $this->tree($row["id"], $locale);

            $return[$i] = $data;

            unset($data);

            $i++;
        }

        return $return;

    }
    else {
        return NULL;
    }
}

И дерево HTML:

function backend_tree($array = null, $class = null)
{
    if(null == $array)
        return false;

    $return = '<ol';

    if(null != $class)
        $return .= ' class="'.$class.'"';

    $return .= '>';

    foreach($array as $item)
    {
        $return .= '<li id="id-'.$item["id"].'"><div>'.$item["titulo"];
        $return .= '<div class="edit">'.anchor("/admin/carta/edit/".$item["id"], " ", array("class" => "sortableEdit")).' '.anchor("/admin/carta/delete/".$item["id"], " ", array("class" => "sortableDelete")).'</div>';
        $return .= '</div>';
        $return .= backend_tree($item["childs"]);
        $return .= '</li>';
    }

    $return .= '</ol>';

    return $return;
}
0

Меньше запросов - значит JOIN:-)

Идея - присоедините его к языку - так что вы получите 3 строки на страницу и обработаете ее в связанном массиве:-) (например, $result [$ row [ "id" ]] ['title'] = $row [ 'title'];)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню