如何从模板中的模板中提取数据? [F3]

时间:2017-03-30 17:06:30

标签: php fat-free-framework

我正在F3中构建一个简单的测验应用程序。

每个测验都有很多问题。每个问题都有很多(可能是不同的)选项。我正确地设置了我的MySQL数据库和表:(1)Quizzes_table,(2)Questions_table,(3)QuestionOptions_table,(4)......以及其他一些记录用户响应的人。

我不确定如何使用F3结构从更广泛的问题模板中正确调用每个问题的选项。以下是模型的外观:http://www.gauravkeerthi.com/reallymeh-mockup/quiz1.html

这是项目git:https://github.com/gauravkeerthi/reallymeh

QuizController.php :(现在我已经硬编码了quiz1.html链接以进行测试)     

class QuizController extends Controller {

    function beforeroute() {
        // session management if required
        // render header
        echo \Template::instance()->render('header.html');
    }

    function render($f3){
        $quizzes = new Quizzes($this->db);
        $quiz = $quizzes->getById(1)[0];
        $f3->set('quiz',$quiz);

        $thisquiz = new Questions($this->db);
        $questions = $thisquiz->getByQuizId(1);
        $f3->set('questions',$questions);

        echo \Template::instance()->render('quiz1.html');
    }
}

这是quiz1.html中调用选项的部分:

<repeat group="{{ @questions }}" key="{{ @count }}" value="{{ @question }}">
     <div class="row">
        <div class="col-md-6">
           <h5>{{ @count + 1 }}. {{ @question.text }}</h5> 
        </div>
        <div class="col-md-6">
           <select class="form-control bg-silver"> 
              <include href="options.html" with="id={{@question.id}}" />                                           
           </select>                     
        </div>
     </div>    
</repeat>

这就是我被困住的地方:我希望实现像“QuestionOptionsController”这样的东西,我使用getByQuestionId($ question.id)并从QuestionOptions中提取所有数据并用数据库填充select。所以从本质上讲,我希望选项看起来像这样(但显然是错误的,因为我现在无法提取正确的数据)。

我希望的options.html将数据从表中提取到@options:

<repeat group="{{@options}}" value="{{@option}}">
   <option>{{@option.text }}</option>
</repeat>

如何正确地将数据提取到@options?我应该使用QuizController并将所有相关的QuestionOptions_Table数据拉入视图中,然后在视图中对其进行排序(对我来说似乎很麻烦)还是有更好的方法?

1 个答案:

答案 0 :(得分:1)

您可以在QuestionsOptions模型中创建getOptions()模型并实施Questions方法。

class Questions extends \DB\SQL\Mapper {

  function getOptions() {
    $options=new QuestionsOptions($this->db);
    return $options->find(['question=?',$this->id],['order'=>'weight']);
    // NB: field names to be adjusted
  }

  ...

  function __construct(\DB\SQL $db) {
    parent::__construct($db,'Questions_table');
  }

}

然后在您的quiz1.html模板中

<select class="form-control bg-silver">
  <repeat group="@question.getOptions()" value="@option">
    <option>{{ @option.text | esc }}</option>
  </repeat>
</select>

<强>更新

正如您在评论中强调的那样,此解决方案可能被视为打破了关注点的分离。如果我们考虑一下,那就是将模型对象传递给破坏它的视图的整个想法:不仅可以在视图中调用getOptions(),还可以save()调用function render($f3){ $quizzes = new Quizzes($this->db); $quiz = $quizzes->getById(1)[0]; $f3->set('quiz',$quiz->cast()); $thisquiz = new Questions($this->db); $questions = []; foreach ($thisquiz->getByQuizId(1) as $question) { $options = []; foreach ($question->getOptions() as $option) $options[] = $option->cast(); $questions[] = $question->cast()+['options => $options]; } $f3->set('questions',$questions); echo \Template::instance()->render('quiz1.html'); }

为了更严格地分离关注点,我建议cast模型在传递给视图之前。这也带来了HTML编码所有正确的优势。

所以你的控制器看起来像:

<select class="form-control bg-silver">
  <repeat group="@question.options" value="@option">
    <option>{{ @option.text }}</option>
  </repeat>
</select>

您的观点如下:

AlarmManager

如您所见,控制器代码现在看起来有点复杂。但是现在你的视图只处理数组和HTML编码的字符串。