2010-11-12 18 views
8

मेरे पास एक संरचना का प्रतिनिधित्व करने वाली संरचना है और मैं इसे रिकर्सिवइटरेटर का उपयोग करके पुन: सक्रिय करना चाहता हूं। समस्या यह है कि यह केवल शीर्ष-स्तर के प्रश्नों को लौटाता है। मैं क्या गलत कर रहा हूं?PHP रिकर्सिवइटरेटर

पूरे प्रपत्र:

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

प्रश्न:

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


} 

पुनरावृत्ति:

$form = Form::loadById(1); 

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

उत्तर

9

RecursiveIterator पर फिर से शुरू करने के लिए, आपको इसे RecursiveIteratorIterator में लपेटना होगा।

डिफ़ॉल्ट यात्रा मोड केवल पत्ते सूची है पर कुछ उदाहरण देखें। यदि आप भी RecursiveIteratorIterator::SELF_FIRST को

2

ठीक है, जैसा कि आप देख सकते हैं here

public RecursiveIterator RecursiveIterator::getChildren (void) 

Returns an iterator for the current iterator entry. 

विधि को पुनरावर्तक को लागू करने वाली वस्तु को वापस करना चाहिए। आपकी विधि एक साधारण सरणी लौटती है।

मेरा अनुमान है की तरह कुछ वापस जाने के लिए होगा:

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

इसका कारण यह है कि आप एक पुनरावर्ती इटरेटर का उपयोग कर रहे तो यह एक ही प्रकार के पेड़ के प्रत्येक नोड होने की संभावना है (पुनरावर्तक)

+0

के कंस्ट्रक्टर के दूसरे तर्क के रूप में RecursiveIteratorIterator::SELF_FIRST पास करना चाहते हैं, हाँ, मेरे पास अब यह है, लेकिन समस्या केवल शीर्ष-स्तरीय नोड्स है और मैं वास्तव में ' टी पता है कि क्या करना है। मैं पूरा कोड पोस्ट करूंगा। – cypher

+0

ठीक है, मैंने पूरी चीज पोस्ट की है, कृपया इसे देखें। – cypher