Слухи верны! Панель администратора WordPress теперь использует Underscore и Backbone! Это означает, что с минимальными усилиями мы можем начать использовать эти фантастические библиотеки JavaScript в наших собственных плагинах. Этот урок покажет вам, как именно вы можете это сделать. Мы создадим административную часть плагина Quiz. Мы будем использовать простой пользовательский тип записи для сохранения вопросов, а затем в каждом вопросе добавим мета-поле, которое позволит нам ввести до 4 ответов и выбрать правильный. Мы рассмотрим, как использовать шаблоны, как подключаться к событиям нажатия и нажатия клавиш, как сохранять данные обратно в базу данных WordPress и, самое главное, как «вытащить свою правду из Dom» в качестве создателя. Джереми Ашкенас любит это выражать.
Я скажу заранее, что плагин, который мы создаем в этом уроке, может показаться слишком многословным для того, что он выполняет. Это, однако, даст вам отличный обзор мира использования Backbone, и если в будущем вы столкнетесь с проектом, который требует сложного пользовательского интерфейса с большим количеством JavaScript, вы будете хорошо вооружены и готовы привести столь необходимую организацию к вечеринка.
Что мы будем делать
В этой первой части мы настроим серверную часть нашего плагина. Это будет включать в себя настройку файлов и папок, а также реализацию всех функций, которые требуются нашему плагину в PHP. Нам нужно будет:
- Зарегистрируйте пользовательский тип сообщения — для наших вопросов
- Добавьте мета-поле, которое позволит нам вводить ответы на той же странице
- Сохраняйте информацию из мета-полей при сохранении записи
- Сохранить информацию из наших запросов AJAX (через Backbone)
Тогда во второй части …
После того, как мы настроим наш сервер, мы продолжим выводить необходимый HTML-код для нашего мета-блока вместе с данными для каждого ответа в формате JSON. Мы также напишем JavaScript, который связывает все вместе. Мы рассмотрим:
- Вывод базового HTML для мета-блока
- Вывод шаблона на стороне клиента вместе с ответами в формате JSON
- JavaScript должен был связать все это
Я надеюсь, что эта небольшая серия будет интересна для вас, и я с нетерпением жду, чтобы помочь вам начать работу с Backbone.js в плагине WordPress.
Что мы будем строить
Этот небольшой плагин будет использовать пользовательский тип сообщения для сохранения вопросов. Затем в мета-поле мы создадим четыре входа, которые позволят пользователям вводить возможные ответы на текущий вопрос и выбирать, какой из них является правильным. При изменении ответа соответствующая кнопка сохранения станет активной. При щелчке мы будем использовать встроенный метод Backbone model.save() для сохранения данных обратно в базу данных WordPress. Кроме того, когда ответы записываются во входные данные, поле выбора ниже автоматически обновит свои значения, так как будет искать изменения в моделях. Все эти вещи относительно просты в работе с Backbone, и после прочтения этого руководства вы сможете перейти на новый уровень с помощью их использования в WordPress.
Есть много чего, так что давайте начнем!
1. Создайте плагин
Нам нужно сделать все обычные первые шаги, связанные с любым плагином — создать папки с файлами.
- Создайте папку с именем wp_quiz
- Создайте файл PHP внутри с тем же именем
- Создайте папку с именем js
- Создайте папку с именем src
Структура вашей папки должна выглядеть следующим образом.
2. Добавьте заголовок плагина
Внутри wp_quiz.php .
|
1
2
3
4
5
6
7
8
|
/*
Plugin Name: WP Quiz
Plugin URI: http://wp.tutsplus.com/author/shaneosbourne/
Description: An example of using Backbone within a plugin.
Author: Shane Osbourne
Version: 0.1
Author URI: http://wp.tutsplus.com/author/shaneosbourne/
*/
|
3. Добавить крючки, чтобы создать плагин
Все еще внутри wp_quiz.php , нам нужно сделать следующие вещи:
- Включите наш основной класс плагинов
- Создайте функцию, которая создаст экземпляр класса
- Добавить хук, чтобы вызывать функцию только когда пользователь является администратором
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
/** wp_quiz.php **/
include ‘src/WpQuiz.php’;
// Create an instance of the Plugin Class
function call_wp_quiz() {
return new WpQuiz( ‘admin’ );
}
// Only when the current user is an Admin
if ( is_admin )
add_action( ‘init’, ‘call_wp_quiz’ );
// Helper function
if ( ! function_exists( ‘pp’ ) ) {
function pp() {
return plugin_dir_url( __FILE__ );
}
}
|
Помещение вспомогательной функции pp() в этот файл позволит нам ссылаться на другие файлы относительно корня папки плагина (вскоре вы увидите это в действии).
4. Создайте класс плагина
Внутри папки src создайте файл с именем WpQuiz.php .
В этом классе плагинов нам понадобятся несколько различных методов для выполнения всех следующих задач:
- Зарегистрируйте пользовательский тип сообщения
- Добавить метабокс
- Получить содержимое для мета-блока и вывести в него как HTML, так и некоторые данные JSON
- Прослушивание запросов PUT и сохранение данных в базе данных.
- Сохраняйте данные нашего мета-бокса при обычных действиях «сохранить»
Прежде чем писать методы, мы собираемся сохранить некоторую информацию в качестве свойств класса. Мы храним эту информацию в верхней части нашего файла классов, чтобы потом было легче вносить изменения. Массив answerIds содержит ключи, которые мы будем использовать в этом плагине для сохранения данных с помощью встроенной функции add_post_meta() .
Добавить свойства
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
/** src/WpQuiz.php **/
class WpQuiz {
// Names of Custom Post Type
public $postTypeNameSingle = ‘Question’;
public $postTypeNamePlural = ‘Questions’;
// Meta Box Stuff
public $metaBoxTitle = ‘Answers’;
public $metaBoxTempl = ‘templates/metabox.templ.php’;
// Question Id’s
public $answerIds = array( ‘quiz-a-1’, ‘quiz-a-2’, ‘quiz-a-3’, ‘quiz-a-4’ );
// Javascript
public $jsAdmin = ‘/js/admin.js’;
}
|
Добавить конструктор
- Сначала мы регистрируем пользовательский тип записи, используя другой вспомогательный метод (который будет показан позже)
- Затем мы регистрируем крюк для загрузки нашего мета-окна
- Нам также нужен отдельный метод для принятия наших запросов AJAX
- Наконец, когда страница загружена, мы хотим сохранить информацию из нашего мета-окна.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
/** src/WpQuiz.php **/
public function __construct( $type ) {
switch ( $type ) {
case ‘admin’ :
// Register the Post Type
$this->registerPostType(
$this->postTypeNameSingle,
$this->postTypeNamePlural
);
// Add the Meta Box
add_action( ‘add_meta_boxes’, array( $this, ‘addMetaBox’ ) );
// Accept an Ajax Request
add_action( ‘wp_ajax_save_answer’, array( $this, ‘saveAnswers’ ) );
// Watch for Post being saved
add_action( ‘save_post’, array( $this, ‘savePost’ ) );
}
}
|
Добавьте Meta Box
- Добавьте файлы JavaScript, необходимые для этого плагина — снова с помощью вспомогательного метода (увидим позже)
- Создайте уникальный идентификатор для этого плагина на основе названия типа сообщения
- Добавьте мета-поле, используя свойства, которые мы установили ранее
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
/** src/WpQuiz.php **/
public function addMetaBox() {
// Load the Javascript needed on this admin page.
$this->addScripts();
// Create an id based on Post-type name
$id = $this->postTypeNameSingle .
// Add the meta box
add_meta_box(
$id,
$this->metaBoxTitle,
array( $this, ‘getMetaBox’ ), // Get the markup needed
$this->postTypeNameSingle
);
}
|
Получить содержимое Meta Box
Здесь мы перебираем наши идентификаторы ответов и создаем массив, содержащий метаданные getOneAnswer с помощью нашего вспомогательного метода getOneAnswer . Мы создаем этот новый массив, чтобы мы могли его кодировать и отправлять в наш шаблон в формате JSON — так, как это нравится Backbone. Мы отправляем данные в наш шаблон с $viewData массива $viewData показанного ниже. Это защищает весь HTML-код и позволяет нам работать над ним в отдельном файле. getTemplatePart метод getTemplatePart , но если вы хотите получить подробное объяснение того, почему я его использую, ознакомьтесь с getTemplatePart процесса — getTemplatePart от логики!
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
/** src/WpQuiz.php **/
public function getMetaBox( $post ) {
// Get the current values for the questions
$json = array();
foreach ( $this->answerIds as $id ) {
$json[] = $this->getOneAnswer( $post->ID, $id );
}
// Set data needed in the template
$viewData = array(
‘post’ => $post,
‘answers’ => json_encode( $json ),
‘correct’ => json_encode( get_post_meta( $post->ID, ‘correct_answer’ ) )
);
echo $this->getTemplatePart( $this->metaBoxTempl, $viewData );
}
|
Получить один ответ — помощник
Мы просто возвращаем массив данных, необходимых в нашем шаблоне. Вы можете думать об этом как о создании единой модели, которая необходима для внешнего интерфейса.
|
1
2
3
4
5
6
7
8
|
/** src/WpQuiz.php **/
public function getOneAnswer( $post_id, $answer_id ) {
return array(
‘answer_id’ => $answer_id,
‘answer’ => get_post_meta( $post_id, $answer_id, true )
);
}
|
Сохранить сообщение
Когда пользователь щелкает, чтобы сохранить сообщение, в котором находится наш мета-бокс, нам нужно сделать пару проверок, чтобы убедиться, что мы сохраняем наш пользовательский тип сообщения и что текущий пользователь имеет правильные разрешения — если обе проверки в порядке, тогда мы сохраните четыре ответа из мета-поля и правильный ответ.
|
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
|
/** src/WpQuiz.php **/
public function savePost( $post_id ) {
// Check that we are saving our Custom Post type
if ( $_POST[‘post_type’] !== strtolower( $this->postTypeNameSingle ) ) {
return;
}
// Check that the user has correct permissions
if ( ! $this->canSaveData( $post_id ) ) {
return;
}
// Access the data from the $_POST global and create a new array containing
// the info needed to make the save
$fields = array();
foreach ( $this->answerIds as $id ) {
$fields[$id] = $_POST[$id];
}
// Loop through the new array and save/update each one
foreach ( $fields as $id => $field ) {
add_post_meta( $post_id, $id, $field, true );
// or
update_post_meta( $post_id, $id, $field );
}
// Save/update the correct answer
add_post_meta( $post_id, ‘correct_answer’, $_POST[‘correct_answer’], true );
// or
update_post_meta( $post_id, ‘correct_answer’, $_POST[‘correct_answer’] );
}
|
Сохранить ответы от запросов Ajax
Здесь мы будем получать данные, передаваемые на сервер от Backbone. Мы должны:
- Доступ к данным, отправленным как запрос PUT. Как это будет в формате JSON, нам нужно декодировать его
- Еще раз проверьте, что текущий пользователь имеет соответствующие разрешения
- Идите и попытайтесь сохранить
- Если либо Добавить, либо Обновление прошло успешно, мы можем просто вернуть вновь сохраненные данные, и Backbone будет считать это успешным
- Если ни один из них не был успешным, мы просто возвращаем 0, чтобы указать сбой
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/** src/WpQuiz.php **/
public function saveAnswers() {
// Get PUT data and decode it
$model = json_decode( file_get_contents( «php://input» ) );
// Ensure that this user has the correct permissions
if ( ! $this->canSaveData( $model->post_id ) ) {
return;
}
// Attempt an insert/update
$update = add_post_meta( $model->post_id, $model->answer_id, $model->answer, true );
// or
$update = update_post_meta( $model->post_id, $model->answer_id, $model->answer );
// If a save or update was successful, return the model in JSON format
if ( $update ) {
echo json_encode( $this->getOneAnswer( $model->post_id, $model->answer_id ) );
} else {
echo 0;
}
die();
}
|
Вспомогательные методы
Вот четыре помощника, упомянутых в приведенных выше фрагментах.
-
canSaveData()— Это просто гарантирует, что текущий пользователь имеет соответствующие разрешения для редактирования / обновления этого сообщения. -
addScripts()— обратите внимание, что здесь мы гарантируем, что передаем 5-й параметр вwp_register_script(). Это загрузит наш пользовательский JavaScript в нижний колонтитул и обеспечит доступность наших данных JSON. Кроме того, если вы используете редактор WordPress в своем плагине, вам не нужно указывать Backbone как зависимость, так как он уже будет доступен для вас. Я включил это здесь ради примера все же. -
registerPostType()— это то, что я часто использую в плагинах. Это просто облегчает жизнь при добавлении нового пользовательского типа сообщения. Он принимает как единственную, так и множественную версии названия, потому что это не всегда так просто, как просто добавить ‘s’. -
getTemplatePart()— я никогда не любил иметь разметку внутри моих методов. Этот маленький помощник позволит использовать отдельный файл шаблона.
|
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
/** src/WpQuiz.php **/
/**
* Determine if the current user has the relevant permissions
*
* @param $post_id
* @return bool
*/
private function canSaveData( $post_id ) {
if ( defined( ‘DOING_AUTOSAVE’ ) && DOING_AUTOSAVE )
return false;
if ( ‘page’ == $_POST[‘post_type’] ) {
if ( ! current_user_can( ‘edit_page’, $post_id ) )
return false;
} else {
if ( ! current_user_can( ‘edit_post’, $post_id ) )
return false;
}
return true;
}
private function addScripts() {
wp_register_script( ‘wp_quiz_main_js’, pp() . $this->jsAdmin , array( ‘backbone’ ), null, true );
wp_enqueue_script( ‘wp_quiz_main_js’ );
}
/**
* Register a Custom Post Type
*
* @param $single
* @param $plural
* @param null $supports
*/
private function registerPostType( $single, $plural, $supports = null ) {
$labels = array(
‘name’ => _x( $plural, ‘post type general name’ ),
‘singular_name’ => _x( «$single», ‘post type singular name’ ),
‘add_new’ => _x( «Add New $single», «$single» ),
‘add_new_item’ => __( «Add New $single» ),
‘edit_item’ => __( «Edit $single» ),
‘new_item’ => __( «New $single» ),
‘all_items’ => __( «All $plural» ),
‘view_item’ => __( «View $single» ),
‘search_items’ => __( «Search $plural» ),
‘not_found’ => __( «No $plural found» ),
‘not_found_in_trash’ => __( «No $single found in Trash» ),
‘parent_item_colon’ => »,
‘menu_name’ => $plural
);
$args = array(
‘labels’ => $labels,
‘public’ => true,
‘publicly_queryable’ => true,
‘show_ui’ => true,
‘show_in_menu’ => true,
‘query_var’ => true,
‘rewrite’ => true,
‘capability_type’ => ‘post’,
‘has_archive’ => true,
‘hierarchical’ => false,
‘menu_position’ => null,
‘supports’ => ( $supports ) ?
);
register_post_type( $single, $args );
}
/**
* Render a Template File
*
* @param $filePath
* @param null $viewData
* @return string
*/
public function getTemplatePart( $filePath, $viewData = null ) {
( $viewData ) ?
ob_start();
include ( «$filePath» );
$template = ob_get_contents();
ob_end_clean();
return $template;
}
|
5. На передний конец
На данный момент мы настроили все необходимое для нашего бэкенда. Пришло время сделать перерыв и подготовиться к следующей части, где мы будем разбираться с клиентскими шаблонами, JavaScript и Backbone.js. Я надеюсь увидеть вас там — это будет хорошо.

