Question

I'm trying to hack together a more efficient (fewer db calls etc) function than WordPress' wp_list_pages without all the possible arguments and stuff. The wp_posts table looks like this:

ID      post_title          post_parent
1       Skate brand no1     5
2       Skate brand no2     5
3       Products            0
4       Bikes               3
5       Skateboards         3
6       About               0
7       Contact             6
8       Surfboards          3

And I want an array that looks like this:

array
    1 => Products
        array
            1 => Bikes
            2 => Skateboards
                array
                    1 => Skate brand no1
                    2 => Skate brand no2
            3 => Surfboards
    2 => About
        array
            1 => Contact

How should I approach this task?

UPDATE!

By replacing about 4 or 5 wp_list_pages on the front page of my site with the code provided by @Gedrox the daily average response time went from a shaky 780-1000ms down to a stable 595-625ms. Amazing!

Était-ce utile?

La solution

If you need full sitemap, you should read all records (one SELECT I assume) and organize in hierarchy in the PHP code.

Sample code:

// TODO: get this from DB
$list = array(
    array('ID' => 1, 'post_title' => 'Skate brand no1', 'post_parent' => 5),
    array('ID' => 2, 'post_title' => 'Skate brand no2', 'post_parent' => 5),
    array('ID' => 3, 'post_title' => 'Products', 'post_parent' => 0),
    array('ID' => 4, 'post_title' => 'Bikes', 'post_parent' => 3),
    array('ID' => 5, 'post_title' => 'Skateboards', 'post_parent' => 3),
    array('ID' => 6, 'post_title' => 'About', 'post_parent' => 0),
    array('ID' => 7, 'post_title' => 'Contact', 'post_parent' => 6),
    array('ID' => 8, 'post_title' => 'Surfboards', 'post_parent' => 3),
);

$rootPages = array();
$pagesById = array();

foreach ($list as $key => &$row) {
    if ($row['post_parent'] == 0) {
        $rootPages[] = &$row;
    }
}

foreach ($list as $key => &$row) {
    $pagesById[$row['ID']] = &$row;
}

foreach ($list as $key => &$row) {
    if ($row['post_parent'] != 0) {
        $pagesById[$row['post_parent']]['children'][] = &$row;
    }
}

print_r($rootPages);

Autres conseils

As far as I can see, in your example you are considering that you may have as many childs as you want.

This approach has to be accomplished by using recursion. In fact, within wordpress' structure, you cannot get the entire tree without making as many queries as the quantity of nodes to check whether the node has children or not.

This is an arborescent structure that allows you to have n children for each node. At the moment, MySQL doesn't support recursive subqueries, so this table logic doesn't allow you to retrieve a complete "path" without the need of log(m) queries (average case, where m is the quantity of nodes of the tree you consider).

This is not as simple as it seems. There's some approachs to retrieve all your tree within one query, and, in that way minimize the sql queries to one, but that requires you to modify your data table.

Here's a more detailed site with examples, where you can see some alternatives you could do.

http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

Edit: I REPEAT: This is not something you can get with 1 mysql query and without recursion. Please don't misunderstand the concept of infinite childs. In @Gedrox's answer, it will only work if you have 3 levels in your tree.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top