Io mi creerei due oggetti: Topic e SubTopic

codice:
class Topic 
{
    public $id;
    public $oggetto
    public $testo
    public $autore
    public $subtopics;
    
    public function __construct($id,$oggetto,$testo,$autore)
    {
        $this->$id = $id;
        $this->$oggetto = $oggetto;
        $this->$testo = $testo;
        $this->$autore = $autore;
    }
    
    public function addSubtopic(SubTopic $sub)
    {
        $this->subtopics[] = $sub;
    }
    
    public function displayTopic()
    {
        // Qui fai quello che vuoi per visualizzare i dati dell'oggetto.
    }
}


class SubTopic
{
    public $parentTopicId;
    public $oggetto;
    public $testo;
    public $autore;
    
    
    public function __construct($id,$oggetto,$testo,$autore)
    {
        $this->$parentTopicId = $id;
        $this->$oggetto = $oggetto;
        $this->$testo = $testo;
        $this->$autore = $autore;
    }
}

A quel punto scansioni le righe della tabella.
Se Id figlio è 0 prendi i dati della riga e istanzi un nuovo Topic (padre) e lo metti in un array.
Consiglio: usa "Id padre" come key, così sarà più facile aggiungere subtopic in seguito)

Se Id figlio è > 0 prendi i dati e istanzi un nuovo Sottotopic (figlio) e lo inserisci nel Topic padre ricercandolo nell'array tramite la key "Id padre".

Alla fine avrai un array di oggetti Topic ognuno con dentro i suoi SubTopic.

Ho scritto il codice di getto e potrebbero esserci errori, ma è giusto per darti una direzione.

p.s. questa non è l'implementazione dell'albero (che rimane una buona idea) è solo come lo farei io.