WordPress как на ладони
wordpress jino

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Подключимся к фильтру 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 = get_option( 'require_name_email' );
	$aria_req = ( $req ? " aria-required='true'" : '' );

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

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

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

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

  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 ( 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://site.ru/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( isset($post) && (int)$post->comment_count > 0 ){
		require_once ABSPATH .'wp-admin/includes/template.php';
		add_action('wp_enqueue_scripts', function(){
			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')");

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

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

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

Extend Comment
Скачано: 140, размер: 0, дата: 6 месяцев назад

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

campusboy 1836wp-plus.ru
WordPress-разработчик. Разработка сайтов и лендингов. Доработка существующих проектов. Сопровождение ресурсов.
Создаем новые поля для комментариев Wordpress 8 комментариев
  • popay6 cайт: clubwp.ru

    Скачал ваш архив. Поставил, в админке работает, а вот на сайте под комментариями вместо звезд Fatal error: Call to undefined function wp_star_rating() in \wp-content\plugins\extend-comment\extend-comment.php on line 91

    После одобрения комментария ошибка исчезает, но звезды не отображаются.

    А и на самом сайте стили не срабатывают и в форме комментария остаются круглеши вместо звезд.

    Ответить4 месяца назад #
  • Ренат

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

    Ответить3 месяца назад #
  • Андрей @

    Не подскажите, как вывести в comments.php где-нибудь к стилям комментария к рейтингом <li id="li-comment-"> что-то типа class="comments_1", если балл 1 округленный или comments_2, если оценка примерно 2. Хочется выделять красным фоном негативные 4
    Спасибо!

    Ответитьмесяц назад #
    • Андрей @

      Нашёл, всё оказалось проще некуда - echo get_comment_meta($comment->comment_ID, 'rating', true ) и подставляй куда хочешь. Спасибо за плагин!

      2
      Ответитьмесяц назад #
  • Вячаслав @

    Здравствуйте. /Вот вчера читал Ваш пост касающийся создание полей в комментариях. И там был пример как их можно сортировать.
    Вот в упор найти не могу. Подкиньте ссылку если не сложно)))

    Ответитьмесяц назад #

Здравствуйте, !

Ваш комментарий