PHP / MySQL вложенная выборка? - PullRequest
0 голосов
/ 05 декабря 2011

Я нахожусь в процессе создания быстрого форума на основе 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 ]

2 голосов
/ 05 декабря 2011

Извлеките все строки в массив, затем зациклите их.

$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 голос
/ 05 декабря 2011

Я дам вам пример, чтобы показать, как это сделать, вот таблицу, которую я буду использовать для примера (после того, как просто добавлю 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");

Некоторые массивы для построения «дерева постов», все parent_id = 0 будут корневыми постами:

$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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...