2010-11-12 9 views
8

Tengo una estructura que representa un formulario y quiero iterar usando RecursiveIterator. El problema es que esto solo devuelve las preguntas de nivel superior. ¿Qué estoy haciendo mal?PHP RecursiveIterator atravesando

entero formulario:

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]); 
    } 
} 

Pregunta:

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; 
    } 


} 

iteración:

$form = Form::loadById(1); 

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

Respuesta

9

Para iterar en un RecursiveIterator, debe envolverlo en un RecursiveIteratorIterator.

ver algunos ejemplos en

El valor predeterminado iteración modo es sólo para enumerar las hojas. Si también desea que los nodos que contienen aparezcan en la iteración, pasan RecursiveIteratorIterator::SELF_FIRST como el segundo argumento del constructor de la RecursiveIteratorIterator

2

Pues bien, como se puede ver here

public RecursiveIterator RecursiveIterator::getChildren (void) 

Returns an iterator for the current iterator entry. 

el método debe devolver un objeto que implementa el iterador. Tu método devuelve una matriz simple.

Mi conjetura sería volver algo como:

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

Esto se debe a que estés usando un iterador RECURSIVO por lo que se espera que tenga cada nodo del árbol del mismo tipo (un iterador)

+0

Sí, ahora tengo esto, pero el problema es sólo los nodos de nivel superior y realmente don' No sé qué hacer. Publicaré el código completo. – cypher

+0

Ok, ya publiqué todo, por favor échale un vistazo. – cypher