如何在模板中的模板中从数据库中提取数据? [F3]
How to pull data from database in a template-within-a-template? [F3]
我正在 F3 中构建一个简单的测验应用程序。
每个测验都有很多问题。每个问题都有许多(可能不同的)选项。我已经正确设置了 MySQL 数据库和 tables:(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 link 用于测试目的)
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 数据从 table 拉到@options:
<repeat group="{{@options}}" value="{{@option}}">
<option>{{@option.text }}</option>
</repeat>
如何正确地将数据拉入@options?我应该使用 QuizController 并将所有相关的 QuestionOptions_Table 数据拉到视图中,然后在视图中对其进行排序(对我来说似乎很乱)还是有更好的方法?
您可以创建一个 QuestionsOptions
模型并在您的 Questions
模型中实施一个 getOptions()
方法。
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()
...
为了更严格地分离关注点,我建议在将模型传递给视图之前 cast 模型。这也带来了 HTML 正确编码所有内容的优势。
所以你的控制器看起来像:
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');
}
您的视图将如下所示:
<select class="form-control bg-silver">
<repeat group="@question.options" value="@option">
<option>{{ @option.text }}</option>
</repeat>
</select>
如您所见,控制器代码现在看起来有点复杂。但是现在您的视图只操作数组和 HTML 编码的字符串。
我正在 F3 中构建一个简单的测验应用程序。
每个测验都有很多问题。每个问题都有许多(可能不同的)选项。我已经正确设置了 MySQL 数据库和 tables:(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 link 用于测试目的)
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 数据从 table 拉到@options:
<repeat group="{{@options}}" value="{{@option}}">
<option>{{@option.text }}</option>
</repeat>
如何正确地将数据拉入@options?我应该使用 QuizController 并将所有相关的 QuestionOptions_Table 数据拉到视图中,然后在视图中对其进行排序(对我来说似乎很乱)还是有更好的方法?
您可以创建一个 QuestionsOptions
模型并在您的 Questions
模型中实施一个 getOptions()
方法。
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()
...
为了更严格地分离关注点,我建议在将模型传递给视图之前 cast 模型。这也带来了 HTML 正确编码所有内容的优势。
所以你的控制器看起来像:
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');
}
您的视图将如下所示:
<select class="form-control bg-silver">
<repeat group="@question.options" value="@option">
<option>{{ @option.text }}</option>
</repeat>
</select>
如您所见,控制器代码现在看起来有点复杂。但是现在您的视图只操作数组和 HTML 编码的字符串。