PHP / MySQL嵌套提取?

时间:2011-12-05 04:17:28

标签: php mysql sql mysqli

我正在制作一个基于PHP的快速论坛,论坛中的每个帖子都会显示在其“父”帖子下,但略微缩进。

要按顺序获取所有帖子,我有以下功能:

    private function getData($pid, $offset)
    {
            $sql = 'SELECT id, subject, date 
                    FROM post 
                    WHERE forum_id = ? AND parent_id = ?';
            $sth = $this->db->prepare($sql);
            $sth->bind_param("ii", $this->id, $pid);
            $sth->bind_result($id, $subject, $date);
            $sth->execute();

            $data = array();

            while ( $sth->fetch() )
            {
                    $row['id'] = $id;
                    $row['subject'] = $subject;
                    $row['date'] = $date;
                    $row['offset'] = $offset;

                    //Add this 'parent' post to the data array
                    $data[] = $row;

                    //Before moving on to next post, get all its children
                    $data[] = $this->getData($id, $offset+1);
            }

            $sth->close();

            return $data;
    }

这不起作用,因为我在关闭并从当前语句处理程序中获取所有数据之前执行另一个查询。

有没有办法可以将查询分开,以免它们相互冲突?或者任何其他方式绕过这个?或者我只需要重新构建我获取数据的方式?

2 个答案:

答案 0 :(得分:2)

将所有行提取到数组中,然后循环遍历它们。

$rows = array();
while ( $sth->fetch() ) {
    $row['id'] = $id;
    $row['subject'] = $subject;
    $row['date'] = $date;
    $row['offset'] = $offset;
    // the cool way is $rows[] = compact('id', 'subject', 'date', 'offset');
    $rows[] = $row;
}
$sth->close();

foreach ($rows as $row) {
                //Add this 'parent' post to the data array
                $data[] = $row;

                //Before moving on to next post, get all its children
                $data[] = $this->getData($id, $row['offset'] + 1);
}

答案 1 :(得分:1)

我将举例说明如何执行此操作,这是我将用于示例的表(仅在添加forum_id之后):

CREATE TABLE msgs (
    id INT NOT NULL AUTO_INCREMENT,
    date DATETIME,
    name VARCHAR(100),
    message TEXT,
    parent_id INT NOT NULL DEFAULT 0
);

然后,通过一个查询执行:

$query = mysql_query("SELECT * FROM msgs ORDER BY id");

构建“posts tree”的一些数组,所有parent_id = 0都是root post:

$all_messages = array(); // Will store all messages
$root_messages = array(); // Will store only the root (or more than one if you allow)

while($row=mysql_fetch_assoc($query)){ // Main loop
        $all_messages[$row['id']] = array(
                'inner_messages'=>array(),
                'date'=> $row['date'],
                'name'=> $row['name'],
                'message'=>$row['message'],
                'id'=>$row['id']
                );
        if($row['parent_id']=='0'){ // If is a root post
        $root_messages[] = &$all_messages[$row['id']];
        }else{ // If not a root post, places within parent message
        $all_messages[$row['parent_id']]['inner_messages'][] = &$all_messages[$row['id']];
        }
}

现在打印,使用递归:

function writeTree($msgs){
    foreach($msgs as $m){
        echo '<div>';
        echo '<h2>'.$m['name'].' ('.$m['date'].')</h2>';
        echo '<div class="text">'.$m['message'].'</div>';
        writeTree($m['inner_messages']);
        echo '</div>';
    }
}
writeTree($root_messages);