WordPress как на ладони
Очень Удобный и Быстрый Хостинг для сайтов на WordPress. Пользуюсь сам и вам рекомендую!

Создаем новые поля для комментариев WordPress

Встречаются задачи, когда нужно добавить произвольные поля в форму комментариев WordPress, например поле для ввода телефона, адреса, оценки, настроения и так далее. Тут-то нам и пригодятся знания о хуках в WordPress (событиях и фильтрах), которые позволят вмешаться в стандартный функционал движка и добавить новые поля в комментарии.

В этой статье мы добавим три новых поля в форму комментария WordPress:

  • два текстовых поля: номер телефона и название комментария.
  • и одно поле выбора - радио-кнопки для оценки текущей статьи.

А также, научимся сохранять их в метаполя комментария и выведем эти поля в админке, чтобы их можно было видеть и редактировать.

Как лучше создавать новые поля?

Расширить форму комментария можно, отредактировав оригинальную тему, создав дочернюю тему или создав плагин. Модифицировать оригинальную тему проще, чем создавать дочернюю, но тут есть серьезный недостаток: все усилия будут утеряны, если тему обновить. Но еще лучше создать плагин, потому что так настраиваемая форма комментариев будет работать на всех темах (за исключением тех, в которых форма комментариев добавляется нестандартно).

Пойдем по пути создания плагина для WordPress, к тому же делается это очень просто. Назовём плагин "Расширенные комментарии".

Создание плагина для расширения формы комментариев

Создадим в папке с плагинами новую папку с именем extend-comment, а внутри неё файл extend-comment.php. Теперь, чтобы WordPress увидел плагин, ему нужно указать специальные комментарии-заголовки:

<?php
/**
 * Plugin Name: Расширенные комментарии
 * Description: Добавляет произвольные поля в форму комментариев.
 * Plugin URI: https://wp-kama.ru/8342
 * Author: Campusboy
 * Author URI: https://wp-plus.ru/
 *
 * Version: 1.0
 */

Заходим в раздел админки "Плагины" и видим наш плагин:

Его уже можно активировать, но на данный момент он "пустой" и никаких функций пока не выполняет...

Создание полей для неавторизованных пользователей

Подключимся к фильтру comment_form_default_fields и "дополним" массив с дефолтными полями WordPress (автор, email, url). В коде ниже мы заменяем код дефолтных полей формы и добавляем новое поле "Телефон".

add_filter( 'comment_form_default_fields', 'extend_comment_custom_default_fields' );

function extend_comment_custom_default_fields( $fields ) {

	$commenter = wp_get_current_commenter();
	$req_name_email = get_option( 'require_name_email' );

	$fields['author'] = sprintf(
		'<p class="comment-form-author">
			<label for="author">%s</label>%s
			<input id="author" name="author" type="text" value="%s" size="30" tabindex="1"%s />
		</p>',
		__( 'Name' ),
		$req_name_email ? '<span class="required">*</span>' : '',
		esc_attr( $commenter['comment_author'] ),
		$req_name_email ? " aria-required='true'" : ''
	);

	$fields['email'] = sprintf(
		'<p class="comment-form-email">
			<label for="email">%s</label>%s
			<input id="email" name="email" type="text" value="%s" size="30"  tabindex="2"%s />
		</p>',
		__( 'Email' ),
		$req_name_email ? '<span class="required">*</span>' : '',
		esc_attr( $commenter['comment_author_email'] ),
		$req_name_email ? " aria-required='true'" : ''
	);

	$fields['url'] = sprintf(
		'<p class="comment-form-url">
			<label for="url">%s</label>
			<input id="url" name="url" type="text" value="%s" size="30"  tabindex="3" />
		</p>',
		__( 'Website' ),
		esc_attr( $commenter['comment_author_url'] )
	);

	$fields['phone'] = sprintf(
		'<p class="comment-form-phone">
			<label for="phone">%s</label>
			<input id="phone" name="phone" type="text" size="30" tabindex="4" />
		</p>',
		__( 'Phone' )
	);

	return $fields;
}

Код прекрасно работает, но если не нужно изменять вид дефолтных полей, то его можно упростить, а именно, добавить только своё поле:

add_filter('comment_form_default_fields', 'extend_comment_default_fields');
function extend_comment_default_fields($fields) {

  $fields[ 'phone' ] = '<p class="comment-form-phone">'.
	'<label for="phone">' . __( 'Phone' ) . '</label>'.
	'<input id="phone" name="phone" type="text" size="30"/></p>';

  return $fields;
}

Данные поля отображаются, когда пользователь не зарегистрирован. Если пользователь авторизован, то ему отобразиться только поле ввода комментария.

Создание полей для всех пользователей

На следующем шаге мы добавим текстовое поле для заголовка комментария и список радио-кнопок для оценки статьи (рейтинг статьи в комментариях).

Эти поля не могут быть добавлены к полям по умолчанию, как сделано выше, потому что нужно дать возможно вводить их и зарегистрированным пользователям. Для этого используем событие comment_form_logged_in_after, которое срабатывает только для зарегистрированных пользователей. Подключившись к нему, мы добавим новые поля до поля ввода комментария.

Добавление комментария авторизованным пользователем

А чтобы показать поля для незарегистрированных пользователей, используем событие comment_form_after_fields, которое отобразит наши поля ниже полей по умолчанию (автор, email, url).

Добавление комментария неавторизованным пользователем

Т.е. в результате нужно вывести поля в момент срабатывания одного из событий:
comment_form_logged_in_after или comment_form_after_fields.

// Добавляем поля для всех пользователей
add_action( 'comment_form_logged_in_after', 'extend_comment_custom_fields' );
add_action( 'comment_form_after_fields', 'extend_comment_custom_fields' );
function extend_comment_custom_fields() {

	echo '<p class="comment-form-title">'.
			  '<label for="title">' . __( 'Comment Title' ) . '</label>'.
			  '<input id="title" name="title" type="text" size="30"/></p>';

	echo '<p class="comment-form-rating">'.
			  '<label for="rating">'. __('Rating') . '<span class="required">*</span></label>
			  <span class="commentratingbox">';

	for( $i=1; $i <= 5; $i++ ){
		echo '
		<label class="commentrating" style="display:inline-block;">
			<input type="radio" name="rating" id="rating" value="'. $i .'"/> '. $i .'   
		</label>';
	}

	echo'</span></p>';
}

Чтобы отобразить 5 радио-кнопок для рейтинга, запускаем цикл. Этот участок кода можно изменить под себя, к примеру вместо 5 указать 10.

Сохранение данных из полей во фронт-энде

Поля для формы комментариев добавлены, но они бесполезны, пока нет алгоритма сохранения данных. Чтобы реализовать этот механизм, используем хук comment_post. Предусмотрим сохранение только непустых данных, чтобы не загромождать базу данных пустыми строками.

Для добавления метаданных комментария используем функцию add_comment_meta().

add_action( 'comment_post', 'save_extend_comment_meta_data' );
function save_extend_comment_meta_data( $comment_id ){

	if( !empty( $_POST['phone'] ) ){
		$phone = sanitize_text_field($_POST['phone']);
		add_comment_meta( $comment_id, 'phone', $phone );
	}

	if( !empty( $_POST['title'] ) ){
		$title = sanitize_text_field($_POST['title']);
		add_comment_meta( $comment_id, 'title', $title );
	}

	if( !empty( $_POST['rating'] ) ){
		$rating = intval($_POST['rating']);
		add_comment_meta( $comment_id, 'rating', $rating );
	}

}

Обратите внимание, что для защиты мы очищаем поля через sanitize_text_field().

Теперь, после публикации комментария в базе появятся подобные строчки:

Добавленные метаданные для комментария

Проверка заполнения обязательных полей

Поле рейтинга мы сделали обязательным. Но сейчас комментарий публикуется, даже если это поле не заполнено. Реализуем механизм проверки. Для этого используем фильтр preprocess_comment и, если рейтинг не был выставлен, отобразим текст об ошибке, не добавляя комментарий в базу данных:

// Проверяем, заполнено ли поле "Рейтинг"
add_filter( 'preprocess_comment', 'verify_extend_comment_meta_data' );
function verify_extend_comment_meta_data( $commentdata ) {

	// ничего не делаем если это ответ на комментарий
	if ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] === 'replyto-comment' ) {
		return $commentdata;
	}

	if ( empty( $_POST['rating'] ) || ! (int)$_POST['rating'] ) {
		wp_die( __( 'Error: You did not add a rating. Hit the Back button on your Web browser and resubmit your comment with a rating.' ) );
	}

	return $commentdata;
}

Отображение содержимого метаполей во фронт-энде

С добавлением метаданных разобрались. Теперь возникает вопрос: как получить и отобразить метаданные комментария в форме? Для получения метаданных будем использовать функцию get_comment_meta().

Изменить код формы и добавить туда нужные данные можно через фильтр comment_text.

Два варианта вывода рейтинга

Рассмотрим 2 варианта, как можно было бы отобразить рейтинг.

Звёзды рейтинга из собственных картинок

В первом варианте мы будет отображать изображения звёзд, которые должны быть в виде картинок в папке плагина:

add_filter( 'comment_text', 'modify_extend_comment');
function modify_extend_comment( $text ){

  $plugin_url_path = WP_PLUGIN_URL;

  if( $commenttitle = get_comment_meta( get_comment_ID(), 'title', true ) ) {
	$commenttitle = '<strong>' . esc_attr( $commenttitle ) . '</strong><br/>';
	$text = $commenttitle . $text;
  }

  if( $commentrating = get_comment_meta( get_comment_ID(), 'rating', true ) ) {
	$commentrating = '<p class="comment-rating">  <img src="'. $plugin_url_path .
	'/extend-comment/images/'. $commentrating . 'star.gif"/><br/>Rating: <strong>'. $commentrating .' / 5</strong></p>';
	$text = $text . $commentrating;
	return $text;
  } else {
	return $text;
  }
}

В коде мы:

  • Получаем ссылку на папку с комментариями.

  • Проверяем наличие заголовка комментария и, если есть, добавляем его перед основным содержимым комментария.

  • Проверяем наличие рейтинга и, если есть, добавляем его после основного содержимого комментария.

Если, к примеру, пользователь поставил четверку, то путь к картинке будет: http://example.com/wp-content/plugins/extend-comment/images/4star.gif. Естественно, картинки должны существовать...

Звёзды рейтинга из иконочного шрифта Dashicons

Второй вариант по алгоритму такой же, но тут будем использовать родную функцию WordPress wp_star_rating(), которая сама добавит красивые иконки звёзд:

// Отображение содержимого метаполей во фронт-энде
add_filter( 'comment_text', 'modify_extend_comment');
function modify_extend_comment( $text ){
	global $post;

	if( $commenttitle = get_comment_meta( get_comment_ID(), 'title', true ) ) {
		$commenttitle = '<strong>' . esc_attr( $commenttitle ) . '</strong><br/>';
		$text = $commenttitle . $text;
	}

	if( $commentrating = get_comment_meta( get_comment_ID(), 'rating', true ) ) {

		$commentrating = wp_star_rating( array (
			'rating' => $commentrating,
			'echo'=> false
		));

		$text = $text . $commentrating;
	}

	return $text;
}

Во фронт-энде функция wp_star_rating() не работает, её надо подключить. Также нужно подключить шрифты 'dashicons'.

Проверим, есть ли у записи комментарии и, если есть, подключим файл с функцией и шрифт:

add_action( 'wp_enqueue_scripts', 'check_count_extend_comments' );
function check_count_extend_comments(){
	global $post;

	if( $post && (int) $post->comment_count > 0 ){
		require_once ABSPATH .'wp-admin/includes/template.php';

		wp_enqueue_style( 'dashicons' );

		$stars_css = '
		.star-rating .star-full:before { content: "\f155"; }
		.star-rating .star-empty:before { content: "\f154"; }
		.star-rating .star {
			color: #0074A2;
			display: inline-block;
			font-family: dashicons;
			font-size: 20px;
			font-style: normal;
			font-weight: 400;
			height: 20px;
			line-height: 1;
			text-align: center;
			text-decoration: inherit;
			vertical-align: top;
			width: 20px;
		}
		';

		wp_add_inline_style( 'dashicons', $stars_css );
	}

}

Шрифт 'dashicons' имеет объем в 45,3Кб без gzip сжатия и 28.3Кб с включенным на сервере сжатием. А сколько будут занимать места ваши картинки? Какой из способов выбрать - решать вам.

Вывод метаполей в админке

На этом создание плагина можно было бы закончить, но что если надо будет изменить метаданные комментария? Поэтому продолжим дорабатывать плагин и добавим возможность изменять метаполя на странице редактирования комментариев в админке.

Для этого добавим метаполя на страницу редактирования комментария с помощью хука add_meta_boxes_comment и функции add_meta_box(). Другими словами, мы ждем действие add_meta_boxes_comment (начало отрисовки дефолтных полей) и с помощью add_meta_box() добавляем новые к имеющимся.

<?php
// Добавляем новый метабокс на страницу редактирования комментария
add_action( 'add_meta_boxes_comment', 'extend_comment_add_meta_box' );
function extend_comment_add_meta_box(){
	add_meta_box( 'title', __( 'Comment Metadata - Extend Comment' ), 'extend_comment_meta_box', 'comment', 'normal', 'high' );
}

// Отображаем наши поля
function extend_comment_meta_box( $comment ){
	$phone  = get_comment_meta( $comment->comment_ID, 'phone', true );
	$title  = get_comment_meta( $comment->comment_ID, 'title', true );
	$rating = get_comment_meta( $comment->comment_ID, 'rating', true );

	wp_nonce_field( 'extend_comment_update', 'extend_comment_update', false );
	?>
	<p>
		<label for="phone"><?php _e( 'Phone' ); ?></label>
		<input type="text" name="phone" value="<?php echo esc_attr( $phone ); ?>" class="widefat" />
	</p>
	<p>
		<label for="title"><?php _e( 'Comment Title' ); ?></label>
		<input type="text" name="title" value="<?php echo esc_attr( $title ); ?>" class="widefat" />
	</p>
	<p>
		<label for="rating"><?php _e( 'Rating: ' ); ?></label>
		<span class="commentratingbox">
		<?php
		for( $i=1; $i <= 5; $i++ ){
		  echo '
		  <span class="commentrating">
			<input type="radio" name="rating" id="rating" value="'. $i .'" '. checked( $i, $rating, 0 ) .'/>
		  </span>';
		}
		?>
		</span>
	</p>
	<?php
}

Этот код похож на тот, который выводил поля в форме комментаривания в посте, и выполняет следующие действия:

  • Получает данные метаполей.

  • wp_nonce_field() выводит проверочное (защитное, одноразовое) скрытое поле для формы, повышая безопасность.

  • Очищает содержимое метаполей с помощью esc_attr() и выводит на экран. Ничего не проверяет. Если данных нет, то поле будет пустое.

  • При выводе радио-кнопок проверяет, какое значение было выбрано и помечает html атрибутом checked='checked' с помощью функции checked().

Сохранение метаполей в админке

На этом шаге необходимо создать механизм сохранения измененных данных на странице редактирования комментария. Это очень похоже на процесс сохранения метаданных из формы комментариев во фронд-энде.

add_action( 'edit_comment', 'extend_comment_edit_meta_data' );
function extend_comment_edit_meta_data( $comment_id ) {
	if( ! isset( $_POST['extend_comment_update'] ) || ! wp_verify_nonce( $_POST['extend_comment_update'], 'extend_comment_update' ) )
	return;

	if( !empty($_POST['phone']) ){
		$phone = sanitize_text_field($_POST['phone']);
		update_comment_meta( $comment_id, 'phone', $phone );
	}
	else
		delete_comment_meta( $comment_id, 'phone');

	if( !empty($_POST['title']) ){
		$title = sanitize_text_field($_POST['title']);
		update_comment_meta( $comment_id, 'title', $title );
	}
	else
		delete_comment_meta( $comment_id, 'title');

	if( !empty($_POST['rating']) ){
		$rating = intval($_POST['rating']);
		update_comment_meta( $comment_id, 'rating', $rating );
	}
	else
		delete_comment_meta( $comment_id, 'rating');

}

Здесь мы подключимся к хуку edit_comment и делаем следующее:

  • Проверим nonce-код и если проверка не пройдет - остановим выполнение функции.

  • Проверим переданные данные по каждому полю и если у какого-то поля его нет - удалим само метаполе, чтобы не занимало место в базе данных. Если поле есть обновляем его и незабываем очищать для безопасности.

Удаление плагина

Наш собственный плагин, расширяющий функционал формы комментирования готов!

Единственное, правилом хорошего тона считается удаление данных, создаваемые плагином, в данном случае - наших метаполей. Ведь если удалить плагин, то данные плагина останутся никому не нужными...

Мы уже рассказывали, как правильно удалить плагин WordPress, потому в корне плагина создадим файл uninstall.php и пропишем в него:

if( ! defined('WP_UNINSTALL_PLUGIN') ) exit;

global $wpdb;

$wpdb->query("DELETE FROM $wpdb->commentmeta WHERE meta_key IN ('phone', 'title', 'rating')");

Вывод среднего рейтинга

По просьбам в комментариях были добавлены две функции, которые можно использовать в своих шаблонах (объект поста должен присутствовать на тот момент).

/**
 * Возвращает средний рейтинг поста.
 *
 * @return string
 */
get_the_extend_comment_post_rating();

// Если было 3 оценки (4, 4, 3) , то выведет 3.6666666666666665
echo get_the_extend_comment_post_rating();

/**
 * Возвращает HTML блок со средним рейтингом в виде звездочек для текущего поста.
 *
 * @see wp_star_rating()
 *
 * @return string
 */
get_the_extend_comment_post_star_rating();

// Пусть оценки те же, что в примере выше.
echo get_the_extend_comment_post_star_rating();

Выведет HTML код (Визуально как выглядят звёзды было показано выше):

<div class="star-rating">
	<span class="screen-reader-text">3,7 rating</span>
	<div class="star star-full" aria-hidden="true"></div>
	<div class="star star-full" aria-hidden="true"></div>
	<div class="star star-full" aria-hidden="true"></div>
	<div class="star star-half" aria-hidden="true"></div>
	<div class="star star-empty" aria-hidden="true"></div>
</div>

Подведем итоги

В этой статье мы разобрались:

Данный плагин можно еще улучшать и дорабатывать - всё зависит от поставленных задач. Ну а пока мы научились изменять дефолтную форму комментирования WordPress и сделали её более привлекательной для пользователя.

Extend Comment
Плагин размещён на GitHub, поэтому можете оставлять свои пожелания и предлагать улучшения там. Или в комментариях к этой статье.
Скачано: 1268, размер: 16KB

Статья создана на базе статьи "How To Add Custom Fields In A WordPress Comment Form" с авторскими правками и дополнениями.

campusboy 4742youtube.com/c/wpplus
Создатель YouTube канала wp-plus, на котором делюсь своим опытом. Активный пользователь wp-kama.ru. WordPress-разработчик. Разработка сайтов и лендингов. Доработка существующих проектов. Сопровождение ресурсов.
Редакторы: Kama 9602
24 комментария
Полезные 1Вопросы 2 Все
    Войти