2010-11-12 29 views
8

J'ai une structure représentant un formulaire et je veux l'itérer en utilisant RecursiveIterator. Le problème est que cela ne renvoie que les questions de niveau supérieur. Qu'est-ce que je fais mal?PHP RecursiveIterator traversant

forme entière:

class Form implements RecursiveIterator{ 
    private $id; 
    private $caption; 
    private $other_text; 
    private $questions = array(); 
    private $current; 

    private function __construct(DibiRow $row){ 
     $this->id = $row->id; 
     $this->caption = $row->caption; 
     $this->other_text = $row->other_text; 
     $this->loadQuestions(); 
    } 

    private function loadQuestions(){ 
     $questions = dibi::query('SELECT * FROM cyp_questions WHERE form_id = %i AND parent_id IS NULL', $this->id); 
     while($question = $questions->fetch()) $this->questions[] = new Question($question->question_id, $question->type, $question->caption, $question->other_text, $question->triggers_unique == 1); 
    } 

    /** 
    * @throws InvalidArgumentException 
    * @param $id 
    * @return Form 
    */ 
    public static function loadById($id){ 
     $form = dibi::query('SELECT * FROM cyp_forms WHERE id = %i', $id)->fetch(); 
     if($form === false) throw new InvalidArgumentException('Form with id '.$id.' was not found.'); 

     return new Form($form); 
    } 

    /** 
    * @throws FormFieldException 
    * @return bool 
    */ 
    public function validate($postfields){ 

    } 

    public function getQuestions(){ 
     return $this->questions; 
    } 

    public function getChildren(){ 
     return $this->questions[$this->current]; 
    } 

    public function hasChildren(){ 
     return count($this->questions) > 0; 
    } 

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

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

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

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

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

Question:

class Question implements RecursiveIterator{ 
    private $id; 
    private $type; 
    private $answers = array(); 
    private $subquestions = array(); 
    private $other_text; 
    private $triggers_unique; 
    private $caption; 
    private $current = 0; 


    public function __construct($id, $type, $caption, $other_text = null, $triggers_unique = false){ 
     $this->id = $id; 
     $this->type = $type; 
     $this->caption = $caption; 
     $this->other_text = $other_text; 
     $this->triggers_unique = $triggers_unique; 
     $this->setSubQuestions(); 

    } 

    private function setSubQuestions(){ 
     $questions = dibi::query('SELECT * FROM cyp_questions WHERE parent_id = %i', $this->id); 
     while($question = $questions->fetch()) $this->subquestions[] = new Question($question->question_id, $question->type, $question->caption, $question->other_text, $question->triggers_unique == 1); 
    } 

    public function getOtherText(){ 
     return $this->other_text; 
    } 

    public function getCaption(){ 
     return $this->caption; 
    } 

    public function addAnswer($answer){ 
     $this->answers[] = $answer; 
    } 

    public function getChildren(){ 
     return $this->subquestions[$this->current]; 
    } 

    public function hasChildren(){ 
     return count($this->subquestions) > 0; 
    } 

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

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

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

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

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

    public function getAnswers(){ 
     return $this->answers; 
    } 


} 

Iteration:

$form = Form::loadById(1); 

foreach($form as $question){ 
    echo $question->getCaption().'<br />'; 
} 

Répondre

9

Pour parcourir sur RecursiveIterator, vous devez l'envelopper dans RecursiveIteratorIterator.

Voir quelques exemples à

Le mode par défaut itération est seulement à la liste des feuilles. Si vous voulez aussi que les nœuds contenant apparaissent dans l'itération, passez RecursiveIteratorIterator::SELF_FIRST comme deuxième argument au constructeur du RecursiveIteratorIterator

2

Eh bien, comme vous pouvez le voir here

public RecursiveIterator RecursiveIterator::getChildren (void) 

Returns an iterator for the current iterator entry. 

la méthode doit renvoyer un objet implémentant l'itérateur. Votre méthode retourne un tableau simple.

Je pense serait de retourner quelque chose comme:

public function getChildren(){ 
    return new Question($this->subquestions); 
} 

C'est parce que vous utilisez un iterator RÉCURSIVE il est prévu d'avoir chaque nœud de l'arbre du même type (un itérateur)

+0

Oui, j'ai maintenant ceci, mais le problème est seulement les nœuds de niveau supérieur et je ne sais vraiment pas Je ne sais pas quoi faire. Je posterai tout le code. – cypher

+0

Ok, j'ai posté le tout, s'il vous plaît jetez un coup d'oeil. – cypher