02.10.2017, 13:28
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,990
|
|
Сообщение от Rasy
|
Ты лентяй, а мне мнение лентяя не особо помогает. Лучше минусуй меня, как Rise и будь счастлив.
|
Не надо впадать в детство - это совет. Я уже взрослый человек, такими категориями не мыслю.
Сообщение от Rasy
|
Ты из категории зубрил
|
Не важно к какой категории я отношусь, но вы пишите мягко выражаясь ахинею, а не код. Ну неужто так трудно даже имея вместо sql-таблицы массив поступать так же по логике как и в случае с БД?
Я ничего и не намерен писать, я знаю, что автор поста и с БД тренировался, и знает по крайней мере принципы, а значит если подумает маленько, то способен будет написать более логичную структуру массива и соответственно код с ней работающий.
А вам же подумать над своим:
(int)$arr[$k]['answer'] - это да, необходимо, но посмотрите как при этом организованы ваши данные. А они организованы так, что intval к ним как издевательство. Не буду пояснять почему, сами догадайтесь, вы же в отличие от меня из категории умельцев.
|
|
02.10.2017, 13:38
|
Профессор
|
|
Регистрация: 17.06.2016
Сообщений: 509
|
|
Лентяй, ok
|
|
03.10.2017, 15:39
|
Профессор
|
|
Регистрация: 08.03.2016
Сообщений: 429
|
|
Я усложнил задание.
Теперь на один вопрос может быть несколько правильных ответов. Пользователь должен отметить один или несколько чекбоксов.
$questions = [
1 => [
'question' => 'Сколько будет 2+2?',
'variants' => ['2', '4', '6', '4.0'],
'answers' => ['1', '3']
],
2 => [
'question' => 'Сколько будет 6+6?',
'variants' => ['66', '6', '12'],
'answers' => ['2']
],
3 => [
'question' => 'Найдите несуществующие месяцы',
'variants' => ['Февраль', 'Июндр', 'Сентябрь', 'Авгурст', 'Денабрь'],
'answers' => ['1', '3', '4']
],
];
if(empty($_GET['proverka'])) {
echo '<form action="" method="get">';
$i = 1;
foreach($questions as $num) {
foreach($num as $dano => $v) {
if(gettype($v) == 'array' && $dano == 'variants') {
$j = 0;
foreach($v as $val) {
echo '<label>'.$val.'<input type="checkbox" name="'.$i.'[]" value="'.$j.'"></label> ';
$j++;
}
}
echo '<br>';
if($dano == 'question') {
echo $v . '<br>';
}
}
$i++;
}
echo '<br>';
echo '<input type="submit" name="proverka" value="Проверить">';
echo '</form>';
}
if(!empty($_GET['proverka'])) {
if(count($_GET)-1 < count($questions)) {
die ('Ответьте на все вопросы.');
}
$k = 1;
foreach($questions as $num) {
foreach($num as $dano => $v) {
if($dano == 'answers') {
$rightAnswers = array_diff($_GET[$k], $questions[$k]['answers']);
$countUserAnswer = $_GET[$k];
$countAnswer = $questions[$k]['answers'];
echo '<br>';
if(count($rightAnswers) == 0 && ($countUserAnswer == $countAnswer)) {
$keyAnswer = [];
foreach($_GET[$k] as $userAnswer) {
$keyAnswer[] = $questions[$k]['variants'][$userAnswer];
}
echo $questions[$k]['question'] . '<br>';
echo 'Ваш ответ: ' ;
echo implode(', ', $keyAnswer);
echo ' и это <span style="color: green; font-weight: bold;">правильный ответ</span>.';
echo '<br><br>';
}
else {
$keyAnswer = [];
$keyTrueAnswer = [];
echo $questions[$k]['question'] . '<br>';
echo 'Ваш ответ: ' ;
foreach($_GET[$k] as $userAnswer) {
$keyAnswer[] = $questions[$k]['variants'][$userAnswer];
}
echo implode(', ', $keyAnswer);
echo ' - <span style="color: red; font-weight: bold;">это неправильно</span>.<br>';
echo 'Правильный ответ(ы): ' ;
foreach($questions[$k]['answers'] as $ans) {
$keyTrueAnswer[] = $questions[$k]['variants'][$ans];
}
echo implode(', ', $keyTrueAnswer);
echo '<br><br>';
}
}
}
$k++;
}
}
|
|
03.10.2017, 19:44
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,990
|
|
DivMan,
вы же как-то тренировались с базами и знаете, что в разумной БД уникального идентификатора равного 0 не будет. Если опираясь на это, делать также и с применением массива, то упрощается проверка мусора/опасного.
Первичный индекс вашего массива данных этому соответствует. Правда в РНР можно поступать проще - задать только первому элементу индекс, остальные получат его по возрастанию автоматически, то есть:
$questions = [
1 => [
'question' => 'Сколько будет 2+2?',
'variants' => ['2', '4', '6', '4.0'],
'answers' => ['1', '3']
],
[
'question' => 'Сколько будет 6+6?',
'variants' => ['66', '6', '12'],
'answers' => ['2']
],
.....
А вот дальше все неверно. У вас есть записи в базе, которые имеют уникальные идентификаторы и названия. По этим данным вы строите список, что в качестве value будут содержать опции списка? Можно быть уверенным, что идентификаторы, которые не имеют нулевого значения.
А почем в массиве данных не так - [1=>'2', '4', '6', '4.0']?
Именование полей цифрами, это плохо, могут быть и косяки, вообще имена должны начинаться с буквы. Для построения формы по вашим данным требуется максимум два массива, причем вы определяет данные, и догадываться проверкой что они пришли это плохо, и виноват у вас в этом как раз лишний цикл. А должно быть
Первый цикл - обход массива $questions как ключ=>значение, вложенный цикл как значения берет из значения ключ 'question' и выводит метку поля, берет ключ 'variants' и выводит кнопки формы именуя их как, например, variants[первичный ключ массива $questions] а value индексы variants, которые начинаются с 1. Зачем тут третий цикл?
И проверка буде без всяких if(count($_GET)-1 < count($questions)), что вообще ни к чему, условием будет if(count($_GET) == count($questions)), а для этого не давайте имя кнопки отправки формы, она у вас одна в форме и серверу совсем не нужна. Достаточно проверить наличие ключа variants в массиве $_GET. А проверить правильно или нет, два цикла совсем не нужны, достаточно одного.
Последний раз редактировалось laimas, 03.10.2017 в 20:24.
|
|
03.10.2017, 23:48
|
Профессор
|
|
Регистрация: 08.03.2016
Сообщений: 429
|
|
Спасибо за рекомендации
|
|
04.10.2017, 03:42
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,990
|
|
Рекомендации в руководстве. )
А вы же задав ключи даже забудьте о ереси $i = 1; name="'.$i.'[]", $i++; $k = 1; $_GET[$k], $k++;
Если вы решите еще более расширить это приложение, то возможно появится и управление. Возможно, что одни задачки будут удалены, а другие добавлены. А уникальность означает не только "не повторяющийся", но еще и "используемый единожды" - если будет удалена задачки под индексом 2, то вновь добавляемая ни в коем случае не должна получать этого индекса, только следующий за максимальным в наборе. Какие могут быть $i++?
И проверять нужно истинность входных данных, и в данном случае это можно делать просто:
if($get = array_intersect_key($_GET, $questions) AND count($get) == count($questions)) {
//данные истинны и выбрано все
//и один единственный цикл для разбора входных данных
foreach($get as $key=>$val) {
if((int)$val == $questions[$key]['answers']) {
//данные истинны и ответ правильный
}
}
}
Последний раз редактировалось laimas, 04.10.2017 в 03:45.
|
|
04.10.2017, 09:43
|
Профессор
|
|
Регистрация: 08.03.2016
Сообщений: 429
|
|
Если делать по примеру БД, но наверно придётся создавать для каждого ответа, отдельный ключ?
|
|
04.10.2017, 09:57
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,990
|
|
Сообщение от DivMan
|
придётся создавать для каждого ответа, отдельный ключ?
|
В каком смысле? Индекс массива, это и есть ключ, чем он хуже первичного ключа sql-таблицы? Вот только индекс должен начинаться с 1, тогда и проверка на истинность упрощается.
Но ваш код имеет одну проблему, его структура неверна. А почему, найдите ответ сами.
|
|
04.10.2017, 10:59
|
Профессор
|
|
Регистрация: 08.03.2016
Сообщений: 429
|
|
вот так должно быть?
$questions = [
1 => [
'question' => 'Сколько будет 2+2?',
'variant1' => '2',
'variant2' => '4',
'variant3' => '6',
'answer1' => '1',
'answer2' => '2',
],
|
|
04.10.2017, 11:11
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,990
|
|
Сообщение от DivMan
|
вот так должно быть?
|
Нет, и уже говорилось - именование ключей одного набора как name1, name2, ... это геморрой. Должно быть 'variants' => [1 => '2', '4', '6', '4.0'] и работа с индексами этого массива как с уникальными значениями одного набора.
Я говорю о структуре кода в целом, а не частных его составляющих, в которых много лишнего у вас и необдуманного. А общая структура кода не отвечает решаемой задаче, подумайте почему?
|
|
|
|