Domanda

ho una struttura che rappresenta una forma e voglio iterare utilizzando RecursiveIterator. Il problema è questo restituisce solo le domande di primo livello. Che cosa sto facendo di sbagliato?

forma totale:

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

Domanda:

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


}

Iterazione:

$form = Form::loadById(1);

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

Soluzione

Per iterare su una RecursiveIterator, è necessario avvolgerlo in un RecursiveIteratorIterator.

vedere alcuni esempi a

La modalità di iterazione di default è solo quello di foglie lista. Se si desidera anche i nodi che contengono a comparire nella iterazione, passare RecursiveIteratorIterator::SELF_FIRST come secondo argomento al costruttore della RecursiveIteratorIterator

Altri suggerimenti

Bene, come si può vedere qui

public RecursiveIterator RecursiveIterator::getChildren ( void )

Returns an iterator for the current iterator entry. 

il metodo deve restituire un oggetto che implementa l'iteratore. Il tuo metodo restituisce un array di semplice.

La mia ipotesi sarebbe quella di restituire qualcosa del genere:

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

Questo è perché si sta utilizzando un iteratore RECURSIVE quindi è aspettato di avere ogni nodo dell'albero dello stesso tipo (un iteratore)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top