Checking for children
SELECT queries
Basics #
First of all, what do they mean? left_id is the left boundary of the item, right_id logically is its right boundary - numerically this would be bottom and top boundaries. When the item has no nested items, the values are adjacent (That means right_id is just one higher than left_id). If it has nested items the left_id of the nested item is one higher than its parent's left_id, and its parent's right_id is one higher than the nested item's right_id.
Example:
| Module name | left_id | right_id |
|---|---|---|
| Single | 1 | 2 |
| Parent | 3 | 6 |
| Child | 4 | 5 |
Checking for children #
To determine wheter an item has children, you no longer have to use a separate query. You can now determine this by checking if the left_id and right_id are adjacent. If they are, the item has no chilren; if they aren't, the item does have children. Here's an example code to determine whether an item in array $foo has children:
- Code: Select all
for ($i = 0, $size = sizeof($foo); $i < $size; $i++)
{
(...)
if ($foo[$i]['right_id'] == $foo[$i]['left_id'] + 1)
{
// $foo[$i] doesn't have children!
}
else
{
// $foo[$i] has children!
}
(...)
}
SELECT queries #
left_id is not only used to check for children, it is also used for ordering data. When selecting items from the database, you use left_id in the ORDER BY clause, and parent_id in the WHERE clause, to get the right set of items. Here's an example query that selects all toplevel items:
- Code: Select all
SELECT *
FROM items_table
WHERE parent_id = 0
ORDER BY left_id ASC
You can also go fancy and select a whole tree of items. The first way you would think of is a recursive query - of course, this is not recommended - but there is another, very simple way. This example is based on a part of the loop used in phpBB-3.0's make_jumpbox() function:
- Code: Select all
$right = $padding = 0;
$padding_store = array('0' => 0);
while ($row = $db->sql_fetchrow($result))
{
// If this row's left_id is lower than the previous right_id, it means this is a child of the previous.
if ($row['left_id'] < $right)
{
$padding++;
$padding_store[$row['parent_id']] = $padding;
}
// And if it's higher and not adjacent it's one or more levels higher
else if ($row['left_id'] > $right + 1)
{
$padding = (isset($padding_store[$row['parent_id']])) ? $padding_store[$row['parent_id']] : $padding;
}
$right = $row['right_id'];
(...)
$spacer = '';
for ($i = 0; $i < $padding; $i++)
{
// Set some padding spacer
$spacer .= ' ';
}
$forum_title = $spacer . $forum_title;
(...)
}
// More to come