Добавление возможности оценить ваш пост на WordPress без плагина для всех пользователей, включая незарегистрированных посетителей. Результат вы видите в правом нижнем углу этой инструкции.
Вначале создадим некоторые функции для back-end, а затем разместим код jQuery на front-end. Применим технологию Ajax, которая уже хорошо реализована в движке системы. Классы CSS подходят для Twitter Bootstrap 5.
Разметка HTML
Поместите код в подходящий для вашей темы файл отображения поста. В моём случае это шаблон для single.php
, который расположен по адресу: тема/template-parts/content-single.php
.
<?php if ( 'publish' === get_post_status() ) : ?>
<div id="post-votes" class="btn-group align-items-end h-100 invisible" role="group" aria-label="Post votes">
<button type="button" class="btn btn-sm border-0 p-0"><span class="dashicons dashicons-thumbs-up"></span></button>
<button type="button" class="btn btn-sm border-0 p-0 px-2 disabled">0</button>
<button type="button" class="btn btn-sm border-0 p-0"><span class="dashicons dashicons-thumbs-down"></span></button>
</div>
<?php endif; ?>
Настройка back-end
Отредактируйте файл functions.php
в корневом каталоге темы WP.
Подключение файла main.js
для работы с JavaScript, дополнительную защиту запросов к серверу можно добавить через специальный код 'ajax-nonce'
в хук 'wp_enqueue_scripts'
:
/**
* Enqueue scripts and styles.
*/
function os_scripts() {
wp_enqueue_style( 'dashicons' );
wp_enqueue_script( 'main-js', get_template_directory_uri() . '/assets/js/main.js', array( 'jquery' ), '1.0', true );
wp_localize_script(
'main-js',
'os_ajax',
array(
'ajax_url' => admin_url( 'admin-ajax.php' ),
'ajax_nonce' => wp_create_nonce( 'ajax-nonce' ),
)
);
}
add_action( 'wp_enqueue_scripts', 'os_scripts' );
- Активируем встроенный в CMS набор SVG иконок
'dashicons'
. - Подключаемый скрипт располагается по адресу:
ваша_тема/assets/js/main.js
. Библиотека jQuery установлена в качестве зависимости, поэтому активируется автоматически. - Функция
'wp_localize_script'
в первом параметре содержит название скрипта'main-js'
, к которому добавляем защиту. Второй параметр'os_ajax'
– это уникальное название JavaScript-объекта для взаимодействия с front-end. А в третьем параметре находится массив с данными, путь к файлу'admin-ajax.php'
и сам код защиты'ajax-nonce'
.
Следующие функции установят файл куки, в который будет помещён сериализованный массив PHP, в нём содержится ID постов для исключения повторного нажатия на кнопки Лайк и Дизлайк. Для каждой задействованной записи создаётся скрытое от пользователей мета-поле '_os_post_votes'
, там и хранится информация о количестве голосов.
Функцию 'os_votes_cookie'
можно использовать для комментариев, поэтому я сделал её отдельной (для универсальности):
/**
* Update meta and set cookie array.
*
* @param string $tax Taxonomy type (only 'post' or 'comment').
* @param int $id Current 'post' or 'comment' ID.
* @return int Votes count.
*/
function os_votes_cookie( $tax, $id ) {
if ( 'post' !== $tax && 'comment' !== $tax ) {
return 0;
}
$cookie_name = "{$tax}_votes_" . COOKIEHASH;
$cookie_array = ( isset( $_COOKIE[ $cookie_name ] ) ) ? maybe_unserialize( $_COOKIE[ $cookie_name ] ) : array();
if ( ! is_array( $cookie_array ) || in_array( $id, $cookie_array ) || ! isset( $_POST['status'] ) ) {
wp_send_json_error();
}
$field_type = "_os_{$tax}_votes";
$votes_meta = ( 'post' === $tax ) ? get_post_meta( $id, $field_type, true ) : get_comment_meta( $id, $field_type, true );
$votes = ( ! empty( $votes_meta ) ) ? intval( $votes_meta ) : 0;
$count = ( 'dislike' === $_POST['status'] ) ? -1 : 1;
$output = ( $votes + $count );
$cookie_life = ( time() + ( 30 * DAY_IN_SECONDS ) );
if ( 'post' === $tax ) {
update_post_meta( $id, $field_type, $output );
} elseif ( 'comment' === $tax ) {
update_comment_meta( $id, $field_type, $output );
}
array_push( $cookie_array, $id );
setcookie( $cookie_name, serialize( $cookie_array ), $cookie_life, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true );
return $output;
}
/**
* AJAX post votes.
*/
function os_ajax_post_votes() {
check_ajax_referer( 'ajax-nonce', 'nonce_code' );
if ( ! isset( $_POST['onload'] ) ) {
wp_send_json_error();
}
$output = 0;
$referer = wp_get_referer();
$post_id = url_to_postid( $referer );
if ( 'false' === $_POST['onload'] ) {
$output = os_votes_cookie( 'post', $post_id );
} else {
$output = intval( get_post_meta( $post_id, '_os_post_votes', true ) );
}
wp_send_json_success( $output );
}
add_action( 'wp_ajax_post_votes', 'os_ajax_post_votes' );
add_action( 'wp_ajax_nopriv_post_votes', 'os_ajax_post_votes' );
Дополнение для смартфонов
Далее в JS вы можете видеть вспомогательный класс 'os-mobile'
, так можно определить, что посетитель зашёл на страницу с мобильного устройства и не отображать там всплывающие подсказки Tooltip. Класс добавляется следующим кодом:
/**
* Filters the list of CSS body class names for the current post or page.
*
* @param string[] $classes An array of body class names.
* @return string[] An array with new body classes.
*/
function os_mobile_body_class( $classes ) {
if ( wp_is_mobile() ) {
$classes[] = 'os-mobile';
}
return $classes;
}
add_filter( 'body_class', 'os_mobile_body_class' );
Настройка front-end
Отредактируйте файл тема/assets/js/main.js
, который был создан в предыдущем разделе, и добавьте следующий код:
/**
* File main.js.
*/
( function ( $ ) {
$( document ).ready( function () {
// Votes Tooltip helper.
function osVotedTip( a, b ) {
$( a ).tooltip( {
title: 'Оценка уже сделана!',
} ).tooltip( 'show' );
$( b ).on( 'mouseleave', function () {
$( a ).tooltip( 'dispose' );
} );
}
// Create an AJAX request.
function osAjaxRequest( action, onload = 'true', status = 'like' ) {
return $.ajax( {
url: os_ajax.ajax_url,
type: 'POST',
dataType: 'json',
data: {
nonce_code: os_ajax.ajax_nonce,
action: action,
onload: onload,
status: status,
},
success: function ( response ) {},
} );
}
// AJAX post votes.
$( function () {
let post = '#post-votes';
let votes = '.disabled';
// AJAX by onload.
osAjaxRequest( 'post_votes' ).done( function ( response ) {
if ( 'undefined' !== typeof( response.data ) ) {
$( post ).find( votes ).text( response.data );
}
$( post ).removeClass( 'invisible' );
} );
$( post ).find( 'button.btn' ).not( votes ).one( 'click', function () {
let btn = this;
let target = $( this ).siblings( votes );
let status = 'like';
if ( $( this ).find( '.dashicons' ).hasClass( 'dashicons-thumbs-down' ) ) {
status = 'dislike';
}
// AJAX by click.
osAjaxRequest( 'post_votes', false, status ).done( function ( response ) {
if ( 'undefined' !== typeof( response.data ) ) {
target.text( response.data );
} else {
if ( ! $( 'body' ).hasClass( 'os-mobile' ) ) {
osVotedTip( target, btn );
}
}
} );
if ( ! $( 'body' ).hasClass( 'os-mobile' ) ) {
$( this ).on( 'click', function () {
osVotedTip( target, btn );
} );
}
} );
} );
} );
} )( jQuery );
На этом форуме используется именно такой код, как в примерах. Обсуждение темы открыто, я постараюсь ответить здесь на все вопросы по данной инструкции.
Планирую вести дневник разработки форума, если вы интересуетесь WordPress и вас устроит качество кода, то будет весьма полезно. Стараюсь придерживаться WP Codex, пока только в JS используется Кириллица, скоро доберусь до её оптимизации.
С уважением, админ.
Спасибо большое, скрипт пригодился
Пожалуйста. Есть подобная инструкция и для добавления кнопок оценки в комментариях:
https://onstartup.ru/articles/wordpress/dobavlenie-knopok-lajk-i-dizlajk-v-kommentariyah-wordpress/