Вопросы с множественным выбором — это то, с чем большинство из нас сталкивалось хотя бы раз в жизни. Мы любим их, потому что можем дать правильные ответы, логически думая о предоставляемых возможностях, даже если мы не знаем точного ответа. Кроме того, ответ занимает меньше времени, что делает его таким популярным.
Создание викторины с множественным выбором в WordPress может быть очень интересной и прибыльной задачей. Вы можете использовать его в своем личном блоге, чтобы привлечь больше посетителей, или вы можете создать премиальный раздел с расширенными тестами, или вы можете создавать тесты, посвященные популярным сертификационным экзаменам. Есть множество возможностей сделать его прибыльным.
Этот плагин не поможет вам в создании тестов для построения бизнеса, но мы должны начать с чего-то, чтобы попасть туда, куда мы хотим идти. Так что это было бы хорошим началом для создания тестов и получения прибыли от этого.
Итак, начнем.
Функциональность плагина
Сначала нам нужно собрать требования плагина, прежде чем приступить к разработке или реализации. По сути, мы должны иметь возможность создавать тесты с несколькими вариантами ответов и позволять пользователям проходить тесты и получать результаты.
Итак, давайте посмотрим на подробные требования и компоненты нашего плагина:
- Плагин должен иметь бэкэнд, в который мы можем вставлять вопросы и ответы динамически. Также идеально иметь категории викторины, чтобы группировать тесты в определенные разделы.
- Администратор сайта должен иметь возможность настраивать тесты через страницу настроек.
- У пользователей должен быть веб-интерфейс, где они могут пройти тест.
- После того, как тест завершен, пользователи должны иметь возможность получать оценки и результаты.
Этот урок будет построен в виде серии из двух частей, в которой мы разработаем бэкэнд плагина в первой части, а затем внешний интерфейс плагина во второй части.
Планирование бэкэнда плагина
В этой части мы собираемся сосредоточиться на разработке серверной части плагина, где мы разрабатываем необходимые данные для тестов.
Обычно есть список тестов, каждый из которых содержит определенный список вопросов. С этим плагином мы не собираемся создавать викторины. Мы будем создавать индивидуальные вопросы и назначать их динамически для тестов по запросу.
Теперь мы можем потратить некоторое время на определение компонентов, необходимых для реализации бэкэнда, как указано в следующем разделе.
- Вопросы должны быть созданы в бэкэнде с ответами. Пользовательский тип сообщения будет лучшим решением для реализации вопросов. Поэтому мы собираемся использовать пользовательский тип записи под названием
wptuts_quiz. - Каждый вопрос должен иметь несколько ответов и один правильный ответ. Поля для ответов будут созданы внутри мета-поля на пользовательском экране создания постов.
- Вопросы будут
quiz_categoriesна различныеwptuts_quizпоэтому нам нужна специальная таксономияquiz_categoriesдляwptuts_quizпостаwptuts_quiz. - Затем нам нужно проверить процесс создания вопроса. Мы будем использовать клиентскую проверку jQuery, когда это необходимо при создании вопроса.
- Наконец, нам нужна страница настроек плагина для хранения количества вопросов на тест и продолжительности теста.
Определив необходимые компоненты WordPress, мы можем перейти непосредственно к реализации бэкенда плагина викторины.
Создание вопросов
Процесс создания вопроса состоит из четырех основных разделов: определение пользовательского типа сообщения, определение пользовательской таксономии, назначение пользовательских полей и проверки. Каждый из этих разделов будет обсуждаться с подробным кодом в следующих разделах.
1. Создание пользовательского типа поста вопросов
Нам нужна самая основная форма настраиваемого типа сообщений для вопросов без каких-либо дополнительных настроек. Единственное, что нам нужно учитывать, — это выбор правильного поля для вопроса.
Экран создания записей по умолчанию содержит два поля для заголовка и содержимого. Вы можете выбрать любое из этих полей для вопроса. Я собираюсь выбрать объединение полей заголовка и контента с учетом расширенных возможностей.
Мы будем создавать объектно-ориентированный плагин вместо функционального, поэтому все необходимые действия, шорткоды и инициализации будут выполняться внутри конструктора. Ниже приведен код для реализации типа записи wptuts_quiz .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
class WP_Quiz {
public $plugin_url;
public function __construct() {
$this->plugin_url = plugin_dir_url( __FILE__ );
add_action( ‘init’, array( $this, ‘wpq_add_custom_post_type’ ) );
}
public function wpq_add_custom_post_type() {
$labels = array(
‘name’ => _x( ‘Questions’, ‘wptuts_quiz’ ),
‘menu_name’ => _x( ‘WPTuts Quiz’, ‘wptuts_quiz’ ),
‘add_new’ => _x( ‘Add New ‘, ‘wptuts_quiz’ ),
‘add_new_item’ => _x( ‘Add New Question’, ‘wptuts_quiz’ ),
‘new_item’ => _x( ‘New Question’, ‘wptuts_quiz’ ),
‘all_items’ => _x( ‘All Questions’, ‘wptuts_quiz’ ),
‘edit_item’ => _x( ‘Edit Question’, ‘wptuts_quiz’ ),
‘view_item’ => _x( ‘View Question’, ‘wptuts_quiz’ ),
‘search_items’ => _x( ‘Search Questions’, ‘wptuts_quiz’ ),
‘not_found’ => _x( ‘No Questions Found’, ‘wptuts_quiz’ ),
);
$args = array(
‘labels’ => $labels,
‘hierarchical’ => true,
‘description’ => ‘WP Tuts Quiz’,
‘supports’ => array( ‘title’, ‘editor’ ),
‘public’ => true,
‘show_ui’ => true,
‘show_in_menu’ => true,
‘show_in_nav_menus’ => true,
‘publicly_queryable’ => true,
‘exclude_from_search’ => false,
‘has_archive’ => true,
‘query_var’ => true,
‘can_export’ => true,
‘rewrite’ => true,
‘capability_type’ => ‘post’
);
register_post_type( ‘wptuts_quiz’, $args );
}
}
|
Мы включили поля заголовка и редактора в пользовательский тип сообщения, чтобы использовать его для вопроса. Поскольку функции расположены внутри класса, мы должны использовать $this в наших действиях, фильтрах и шорткодах WordPress для вызова функций.
Кроме того, все параметры, упомянутые в коде, инициализируются значениями по умолчанию.
2. Создание категорий вопросов
Чтобы сгруппировать вопросы в определенные разделы, нам нужно нечто похожее на стандартные категории WordPress. Следовательно, мы будем использовать пользовательскую таксономию под названием quiz_categories . Нам нужно вызвать функцию генерации пользовательской таксономии для действия init как мы это делали ранее. Таким образом, конструктор нашего класса плагина должен быть обновлен следующим кодом.
|
1
|
add_action( ‘init’, array( $this,’wpq_create_taxonomies’ ), 0 );
|
Затем мы можем реализовать функцию wptuts_quiz типа wptuts_quiz как показано в следующем коде.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
function wpq_create_taxonomies() {
register_taxonomy(
‘quiz_categories’,
‘wptuts_quiz’,
array(
‘labels’ => array(
‘name’ => ‘Quiz Category’,
‘add_new_item’ => ‘Add New Quiz Category’,
‘new_item_name’ => «New Quiz Category»
),
‘show_ui’ => true,
‘show_tagcloud’ => false,
‘hierarchical’ => true
)
);
}
|
Я использовал параметры по умолчанию для создания этой пользовательской таксономии. После того, как плагин активирован, ваш тип поста и таксономия будут отображаться, как показано на следующем экране.
3. Создание ответов на вопрос
Далее нам нужно создать несколько ответов на каждый вопрос. В этом плагине максимальное количество ответов на один вопрос будет ограничено пятью.
Вы можете динамически назначать 1-5 ответов на любой вопрос. Также нам необходимо указать правильный ответ из предоставленного списка ответов. Поскольку эти данные связаны с нашими вопросами, мы можем использовать мета-поле с настраиваемыми полями для создания необходимых полей.
Как обычно, нам нужно обновить конструктор следующим кодом:
|
1
|
add_action( ‘add_meta_boxes’, array( $this,’wpq_quiz_meta_boxes’ ) );
|
Рассмотрим следующий код для реализации мета-блоков с полями ответов.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
function wpq_quiz_meta_boxes() {
add_meta_box( ‘quiz-answers-info’, ‘Quiz Answers Info’, array( $this, ‘wpq_quiz_answers_info’ ), ‘wptuts_quiz’, ‘normal’, ‘high’ );
}
function wpq_quiz_answers_info() {
global $post;
$question_answers = get_post_meta( $post->ID, ‘_question_answers’, true );
$question_answers = ( $question_answers == » ) ?
$question_correct_answer = trim( get_post_meta( $post->ID, ‘_question_correct_answer’, true ) );
$html = ‘<input type=»hidden» name=»question_box_nonce» value=»‘ . wp_create_nonce( basename( __FILE__ ) ) . ‘» />’;
$html .= ‘<table class=»form-table»>’;
$html .= ‘<tr><th style=»»><label for=»Price»>Correct Answer</label></th><td><select class=»widefat» name=»correct_answer» id=»correct_answer» >’;
for ( $i = 1; $i <= 5; $i++ ) {
if ( $question_correct_answer == $i ) {
$html .= ‘<option value=»‘ . $i . ‘» selected >Answer ‘ .
}
else {
$html .= ‘<option value=»‘ . $i . ‘»>Answer ‘ .
}
}
$html .= ‘</select></td></tr>’;
$index = 1;
foreach ( $question_answers as $question_answer ) {
$html .= ‘<tr><th style=»»><label for=»Price»>Answer ‘ .
$html .= ‘<td><textarea class=»widefat» name=»quiz_answer[]» id=»quiz_answer’ . $index . ‘» >’ .
$index++;
}
$html .= ‘</tr>’;
$html .= ‘</table>’;
echo $html;
}
|
4. Объяснение кода
- Ответы на каждый вопрос будут храниться в виде строки в кодировке JSON в таблице
post_metaс ключом_question_answers. Таким образом, мы получаем доступ к этому полю, используя функциюget_post_metaчтобы получить текущие значения. - Тогда мы получим правильный ответ на вопрос, используя аналогичный метод. Правильный ответ будет сохранен в виде строки в таблице
post_metaс ключом_question_correct_answer. - Наконец, мы создаем HTML-форму, которая содержит правильный ответ в виде выпадающего списка и возможные ответы в виде пяти полей текстовой области.
- Все существующие значения, полученные с
get_post_metaфункцииget_post_metaбудут присвоены соответствующим полям.
После создания мета-блока вы должны увидеть нечто похожее на следующий экран.
Теперь у нас есть все данные, необходимые для нашего плагина генерации тестов. Следующим шагом является сохранение данных вопроса в базу данных.
Но нам нужно несколько проверок до этого. Итак, давайте перейдем к валидации.
Подтверждение создания вопроса
На данном этапе в процессе создания вопроса у нас нет сложных правил проверки. Поэтому мы собираемся использовать проверки JQuery на стороне клиента перед отправкой.
Здесь нам нужно, admin_enqueue_scripts действие admin_enqueue_scripts было включено в конструктор нашего плагина.
Так что обновите конструктор следующим кодом, прежде чем мы начнем.
|
1
|
add_action( ‘admin_enqueue_scripts’, array( $this, ‘wpq_admin_scripts’ ) );
|
Теперь посмотрите на следующий код для включения необходимых файлов сценариев для проверки.
|
1
2
3
4
5
6
7
|
function wpq_admin_scripts() {
wp_register_script( ‘quiz-admin’, plugins_url( ‘js/quiz.js’, __FILE__ ), array( ‘jquery’ ) );
wp_enqueue_script( ‘quiz-admin’ );
}
|
Используя wp_register_script и wp_enqueue_script , у нас есть специфичный для плагина JS-файл quiz.js для обработки проверок . Проверка будет выполняться с использованием библиотеки jQuery, и поэтому мы установили встроенную библиотеку jQuery в качестве зависимости для нашего специфичного для плагина JavaScript.
Включив сценарии, давайте реализуем фактические проверки в файле quiz.js, как показано в следующем коде.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
jQuery(document).ready(function($) {
$(«#post-body-content»).prepend(‘<div id=»quiz_error» class=»error» style=»display:none» ></div>’);
$(‘#post’).submit(function() {
if ( $(«#post_type»).val() ==’wptuts_quiz’ ) {
return wpq_validate_quizes();
}
});
});
|
Во-первых, мы назначаем пустой элемент div экрану создания записей, чтобы отобразить любые ошибки. Затем мы можем вызвать пользовательскую функцию JS для действия публикации после публикации, проверив правильный тип сообщения, используя #post_type скрытого поля #post_type .
Следующий код содержит реализацию функции wpq_validate_quizes .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
var wpq_validate_quizes = function() {
var err = 0;
$(«#quiz_error»).html(«»);
$(«#quiz_error»).hide();
if ( $(«#title»).val() == » ) {
$(«#quiz_error»).append(«<p>Please enter Question Title.</p>»);
err++;
}
var correct_answer = $(«#correct_answer»).val();
if ( $(«#quiz_answer»+correct_answer).val() == «» ) {
$(«#quiz_error»).append(«<p>Correct answer cannot be empty.</p>»);
err++;
}
if ( err > 0 ) {
$(«#publish»).removeClass(«button-primary-disabled»);
$(«.spinner»).hide();
$(«#quiz_error»).show();
return false;
}
else {
return true;
}
};
|
Код Объяснение
- Сначала мы должны скрыть контейнер ошибок и установить его текущее сообщение об ошибке пустым.
- Затем мы проверяем, существует ли заголовок, так как заголовок обязателен для вопросов.
- Затем мы получаем выбранный правильный ответ и проверяем, является ли поле ответа, связанное с правильным ответом, пустым.
- Когда генерируются ошибки проверки, мы отображаем ошибки в указанном контейнере ошибок и предотвращаем отправку сообщения.
На следующем рисунке показан экран создания поста с пользовательскими сообщениями проверки.
Как только форма успешно подтверждена без ошибок, мы можем перейти к сохранению деталей вопроса в базе данных.
Сохранение деталей вопроса
WordPress предоставляет действие save_post , которое будет выполнено сразу после создания записи. Мы можем определить пользовательскую функцию в действии save_post для сохранения сведений о настраиваемом поле в базе данных.
Как обычно, обновите конструктор save_post действия save_post .
|
1
|
add_action( ‘save_post’, array( $this, ‘wpq_save_quizes’ ) );
|
Реализация функции wpq_save_quizes приведена в следующем коде.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
function wpq_save_quizes( $post_id ) {
if ( ! wp_verify_nonce( $_POST[‘question_box_nonce’], basename( __FILE__ ) ) ) {
return $post_id;
}
if ( defined( ‘DOING_AUTOSAVE’ ) && DOING_AUTOSAVE ) {
return $post_id;
}
if ( ‘wptuts_quiz’ == $_POST[‘post_type’] && current_user_can( ‘edit_post’, $post_id ) ) {
$question_answers = isset( $_POST[‘quiz_answer’] ) ?
$filtered_answers = array();
foreach ( $question_answers as $answer ) {
array_push( $filtered_answers, sanitize_text_field( trim( $answer ) ) );
}
$question_answers = json_encode( $filtered_answers );
$correct_answer = isset( $_POST[‘correct_answer’] ) ?
update_post_meta( $post_id, «_question_answers», $question_answers );
update_post_meta( $post_id, «_question_correct_answer», $correct_answer );
}
else {
return $post_id;
}
}
|
Идентификатор сообщения автоматически передается в эту функцию. Первоначально мы выполняем проверки для одноразового значения и автосохранения. Самое важное перед сохранением — это проверка типа записи.
Если вы пропустите проверку типов записей, этот код будет выполняться для всех типов записей в вашей установке WordPress, включая обычные записи, что может привести к несогласованности данных.
Наконец, мы получаем значения полей наших ответов и поля правильных ответов для сохранения в базе данных с update_post_meta функции update_post_meta . Все пользовательские поля будут сохранены в таблицу post_meta .
Теперь мы завершили процесс создания вопроса. Поскольку мы используем произвольно сгенерированные тесты, вам может понадобиться много вопросов, чтобы увидеть этот плагин в действии. Так что будьте готовы, добавив дополнительные вопросы, прежде чем мы реализуем тест в следующей части.
Страница настроек викторины
Несмотря на то, что это не является обязательным, идеально иметь страницу настроек для нашего плагина, чтобы администратор мог настроить в соответствии со своими предпочтениями.
Итак, давайте реализуем простую страницу настроек, которая будет содержать продолжительность теста и количество вопросов на тест. Нам нужно реализовать действие admin_menu в конструкторе.
|
1
|
add_action( ‘admin_menu’, array( $this, ‘wpq_plugin_settings’ ) );
|
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
function wpq_plugin_settings() {
//create new top-level menu
add_menu_page( ‘WPTuts Quiz Settings’, ‘WPTuts Quiz Settings’, ‘administrator’, ‘quiz_settings’, array( $this, ‘wpq_display_settings’ ) );
}
function wpq_display_settings() {
$html = ‘<div class=»wrap»>
<form method=»post» name=»options» action=»options.php»>
<h2>Select Your Settings</h2>’ .
<table width=»100%» cellpadding=»10″ class=»form-table»>
<tr>
<td align=»left» scope=»row»>
<label>Number of Questions</label><input type=»text» name=»wpq_num_questions» value=»‘ . get_option( ‘wpq_num_questions’ ) . ‘» />
</td>
</tr>
<tr>
<td align=»left» scope=»row»>
<label>Duration (Mins)</label><input type=»text» name=»wpq_duration» value=»‘ . get_option( ‘wpq_duration’ ) . ‘» />
</td>
</tr>
</table>
<p class=»submit»>
<input type=»hidden» name=»action» value=»update» />
<input type=»hidden» name=»page_options» value=»wpq_num_questions,wpq_duration» />
<input type=»submit» name=»Submit» value=»Update» />
</p>
</form>
</div>’;
echo $html;
}
|
Мы можем использовать функцию add_menu_page чтобы добавить страницу настроек в add_menu_page . Функция wpq_display_settings используется для реализации элементов отображения страницы настроек.
Мы использовали два текстовых поля для продолжительности и вопросов для теста. Отправка формы и сохранение данных могут быть обработаны вручную с помощью пользовательского кода, но WordPress предоставляет нам упрощенный метод обновления параметров.
В этом методе вы должны установить действие формы для файла options.php . Затем вам нужно создать скрытое поле с именем action, которое будет содержать значение update . Наконец, нам нужно другое скрытое поле с именем page_options будет содержать имена двух текстовых полей, которые нужно обновить.
Обязательно используйте эти встроенные методы обновления параметров в тех случаях, когда требования для сохранения полей не являются сложными.
После нажатия кнопки «Отправить» данные формы будут автоматически обновляться без какого-либо специального кода.
Что дальше
Мы завершили бэкэнд нашего плагина викторины. Теперь вы можете создавать вопросы и готовиться к следующей части, где мы будем использовать эти вопросы для динамической генерации тестов.
А пока дайте мне знать, как лучше всего реализовать динамический тест на веб-интерфейсе. Имейте в виду, что за один раз будет отображаться только один вопрос. Когда пользователь запрашивает вопрос, он может перейти к следующему вопросу.
Ждем ваших предложений.