2011-07-04 14 views
5

Sto cercando di creare un iteratore come this one, per un elenco di commenti:implementazione multi-livello "iteratore" in PHP

// the iterator class, pretty much the same as the one from the php docs... 
abstract class MyIterator implements Iterator{ 

    public $position = 0, 
     $list; 

    public function __construct($list) { 
    $this->list = $list; 
    $this->position = 0; 
    } 

    public function rewind() { 
    $this->position = 0; 
    } 

    public function current() { 
    return $this->list[$this->position]; 
    } 

    public function key() { 
    return $this->position; 
    } 

    public function next() { 
    ++$this->position; 
    } 

    public function valid() { 
    return isset($this->list[$this->position]); 
    } 
} 

Il commento iteratore:

class MyCommentIterator extends MyIterator{ 

    public function current(){ 
    return new Comment($this->list[$this->position]); 
    }  
} 

E questo è come lo uso:

$comments = GetComments(); // gets the comments from the db 
if($comments): ?> 

    <ol> 
    <?php foreach(new MyCommentIterator($comments) as $comment): ?> 
    <li> 
     <p class="author"><?php echo $comment->author(); ?></p> 

     <div class="content"> 
     <?php echo $comment->content(); ?> 
     </div> 

     <!-- check for child comments and display them --> 

    </li> 
    <?php endforeach; ?> 
    </ol> 

<?php endif; ?> 

Quindi tutto funziona bene, oltre a una cosa: non riesco a capire come elaborare n commenti INTERESSATE :(

L'array $comments restituisce una semplice lista di commenti, come:

[0] => object(
    'id' => 346, 
    'parent' => 0, // top level comment 
    'author' => 'John', 
    'content' => 'bla bla'   
), 

[1] => object(
    'id' => 478, 
    'parent' => 346, // child comment of the comment with id =346 
    'author' => 'John', 
    'content' => 'bla bla'   
) 
... 

ho bisogno di essere in qualche modo in grado di verificare la presenza di commenti bambino (su più livelli) e inserirli prima della </li> ' s dei loro commenti principali ...

Qualche idea?

risposta

1

Si sta utilizzando un array piatto, ma in realtà gli elementi di tale array sono una struttura di dati gerarchica o ad albero.

In pratica stai visualizzando un elenco sequenziale. Forse dovresti prima costruire una struttura dati gerarchica/ad albero, senza visualizzare, e visualizzare successivamente i dati dalla lista ad albero.

/* array */ function FlatArrayToTreeArray(/* array */ $MyFlatArray) 
{ 
    ... 
} 

/* void */ function IterateTree(/* array */ $MyTreeArray) 
{ 
    ... 
} 

/* void */ function Example() { 
    $MyFlatArray = Array(
    0 => object(
     'id' => 346, 
     'parent' => 0, // top level comment 
     'author' => 'John', 
     'title' => 'Your restaurant food its too spicy', 
     'content' => 'bla bla'   
    ), 
    1 => object(
     'id' => 478, 
     'parent' => 346, // child comment of the comment with id =346 
     'author' => 'Mike', 
     'title' => 'Re: Your restaurant food its too spicy', 
     'content' => 'bla bla'   
    ), 
    2 => object(
     'id' => 479, 
     'parent' => 478, // child comment of the comment with id =346 
     'author' => 'John', 
     'title' => 'Re: Your restaurant food its too spicy', 
     'content' => 'bla bla'   
    ), 
    3 => object(
     'id' => 479, 
     'parent' => 346, // child comment of the comment with id =346 
     'author' => 'Jane', 
     'title' => 'Re: Your restaurant food its too spicy', 
     'content' => 'bla bla'   
    ) 
); 

    $MyTreeArray = FlatArrayToTreeArray($myflatarray); 

    IterateTree($MyTreeArray); 
} // function Example() 

Cheers.

3

La ricorsione è un tuo amico.

displaycomment(comment): 
    $html .= "<ol>" . comment->html; 
    foreach comment->child: 
     $html .= "<li>" . displaycomment(child) . "</li>"; 
    $html .= "</ol>"; 
    return $html; 

Tutto il codice visualizzato in questo post è pseudo. Qualsiasi somiglianza con il codice reale, funzionante o rotto, è puramente casuale.

3

Si potrebbe voler esaminare il RecursiveIterator InterfacePHP Manual. Se estendi il tuo iteratore con i metodi di tale interfaccia, puoi ripetere i tuoi commenti con un'istanza di RecursiveIteratorIterator sequenzialmente.

Tuttavia, poiché l'output è un elenco semplice, è necessario occuparsi della logica dei livelli per conto proprio, ad es. inserendo <ol> per profondità in alto e </ol> per profondità in basso.

Utilizzare i flag per controllare l'ordine di attraversamento dei bambini.