Проста кнопка «Подобається» для сайту без плагіну - Блог chomovva

Мені поставили завдання організувати збір інформації щодо лояльністі користувачів до постів сайту «Проект 90». Така інформація використовується для ранжування постів за популярністю. Кнопка «Подобається» від соціальних мереж – один з найпростіших способів отримання такої інформації. Але функції соціальних мереж обов’язково вимагають процедуру реєстрації та авторизації, а це напевно відлякає користувача. Справа в тому, що основна аудиторія сайту «Проект 90» погано володіє навичками роботи за комп’ютером і в мережі інтернет. Тому кнопка “Подобається” повинна бути максимально схожа на аналогічний функціонал соціальних мереж і при цьому не вимагати окремої авторизації. Так само необхыдно додати мінімальний захист від накрутки і більш-менш адекватний лічільник лайків.

Як це реалізувати

Сайт «Проект 90» працює на CSM WordPress, тому в розробці враховані особливості саме цієї системи.

Детальніше про тему, яка використовується на сайті проекту: WordPress-тема для сайту присвяченого заходу.

Я не прихильник використання окремого плагіна для простих завдань, тому кнопка “Подобається” додана в код WordPress-тему, а не підключена окремо.

Для коректного збору інформації про лайки потрібна ідентифікація користувача, так як вона дозволяє уникнути повторного голосування. Ідентифікатор формується за допомогою JavaScript в публічній частині сайту на основі даних про браузер і поточний час. Дані зберігаються в локальному сховищі браузера (детальніше про localStorage). При натисканні на кнопку «Подобається» ідентифікатор користувача передається на сервер і записується в базу даних.

Облік «лайків» на сервері ведеться за допомогою метаполів таблиці wp_postmeta. Щоб не засмічувати базу даних метаполя видаляються при деактивації теми.

meta_idpost_idmeta_keymeta_value
auto$post_id'liked'$user_id

Щоб зменшити кількість запитів на сервер в локальному сховищі браузера створюється масив ідентифікаторів вподобаних постів. При завантаженні сторінки, за допомогою JavaScript порівнюється список ідентифікаторів завантажених постів зі списком вподобаних. На основі цього порівняння додаються класи-стани для кнопок.

Після натискання на кнопку «Мені подобається» на сервер відправляється ідентифікатор користувача і ідентифікатор вподобаного запису. У разі успіху запису додається нове метапол з ідентифікатором користувача. При повторному лайці метапол видаляється. Кількість лайків поста дорівнює кількості метапол. У браузер повертається інформація про скоєну дію і кількість лайків.

Робота кнопки Подобається
Робота кнопки Подобається

Серверна частина

Весь php-код підключається в файлі functions.php теми.

Формування коду кнопки “Подобається”

Формування html-коду кнопки «Подобається» доцільно винести в окрему функцію, яку в подальшому буде зручно використовувати. Ідентифікатор поста і кількість лайків зберігаються в data-аттрибутах кнопки. При натисканні кнопки JavaScript код підхоплює ідентифікатор і передає його на сервер.

function get_like_button( $post_id = false ) {
  if ( ! $post_id ) {
    $post_id = get_the_ID();
  }
  $count = count( get_post_meta( $post_id, '_liked', false ) );
  return sprintf(
    '<button class="like" data-like-id="%1$s" data-liked-count="%2$s"><span class="sr-only">%3$s</span></button>',
    $post_id,
    ( empty( $count ) ) ? '' : esc_attr( $count ),
    __( 'Поставить лайк', THEME_TEXTDOMAIN )
  );
}

Обробка ajax запиту

Інформацію про натискання кнопки “Подобається” сервер отримує через AJAX. Для обробки такого запиту від всіх користувачів потрібно скористатися хукамі wp_ajax_(action) і wp_ajax_nopriv_(action).

Детальніше про використання AJAX на сайті: “Ajax в WordPress“.

function like_processing() {
  // проверяем код безопасности
  if ( isset( $_GET[ 'security' ] ) && wp_verify_nonce( $_GET[ 'security' ], 'liked' ) ) {
    // проверяем есть ли идентификатор поста и пользователя, без этих параметров можно дальше не продолжать
    if ( isset( $_GET[ 'post_id' ] ) && ! empty( $_GET[ 'client_id' ] ) && ! empty( $_GET[ 'client_id' ] ) ) {
      // очищаем идентификатор поста
      $post_id = sanitize_key( $_GET[ 'post_id' ] );
      // очищаем идентификатор пользователя
      $client_id = sanitize_text_field( $_GET[ 'client_id' ] );
      // получаем массив лайком для текущего поста
      $liked = get_post_meta(  $post_id, '_liked', false );
      // инициализируем переменную для ответа браузеру пользователя
      $action = '';
      // провверяем ставил ли уже пользователь лайк текущему посту
      if ( in_array( $client_id, $liked ) ) {
        // усли ставил, то удаляем лайк, и присваиваем соответствующий ответ для переменной $action
        delete_post_meta( $post_id, '_liked', $client_id );
        $action = 'delete';
      } else {
        // добавляем новый лайт и ответ в переменной $action
        add_post_meta( sanitize_key( $_GET[ 'post_id' ] ), '_liked', $client_id, false );
        $action = 'add';
      }
      // формируем ответ браузеру пользователя
      // будет передано количество поставленных лайков и информация
      // о выполненном на сервере действии (добавили или удалили)
      wp_send_json_success( array(
        'action' => $action,
        'count'  => count( get_post_meta(  $post_id, '_liked', false ) ),
      ) );
    }
  }
  // обравыем работу скрипта
  wp_die();
}
// цепляем хуки, action в нашем случае равен 'liked'
add_action( 'wp_ajax_liked', 'like_processing' );
add_action( 'wp_ajax_nopriv_liked', 'like_processing' );

Підключаємо js-скрипт лицьової частини сайту

Для можливості використання AJAX в лицьовій частині сайту треба створити js-змінну ajaxurl. Зробимо це за допомогою функції wp_enqueue_script. Так само передамо і код безпеки (nonce-код), який формується за допомогою функції wp_create_nonce. Код безпеки допоможе відсіяти частину спамерських ботів. Для перевірки інших дій неавторизованих користувачів його використовувати безглуздо.

function liked_scripts() {
  wp_enqueue_script( 'liked', THEME_URL . 'scripts/liked.js', array( 'jquery' ), THEME_VERSION, true );
  wp_localize_script( 'liked', 'ThemeLiked', array(
    'ajaxurl'  => admin_url( 'admin-ajax.php' ),
    'liked'    => wp_create_nonce( 'liked' ),
  ) );
}
add_action( 'wp_enqueue_scripts', 'liked_scripts' );

Використання кнопки в WordPress-темі

Для додавання кнопки до посту потрібно викликати функцію get_like_button ( $post_id ) з параметром ідентифікатор поста. У циклі WordPress цей параметр $post_id є не обов’язковим.

if ( have_post() ) {
  while ( have_post() ) {
    the_post();
    the_title();
    the_excerpt();
    echo get_like_button( get_the_ID() );
  }
}

Клієнтська частина

Клієнтська частина коду знаходиться в файлі liked.js. У ньому формується ідентифікатор користувача, встановлюються класи-стани кнопок “Подобається” та формується запит на сервер. Ідентифікатор користувача це по суті hash-код сформований з рядка з інформацією про браузер, поточну дату та час.

jQuery( document ).ready( function () {

  // функция в которой отправляется AJAX запрос на сервер
  function set_like( $button ) {
    // получаем идентификатор поста (хранится в атрибуте кнопки)
    var post_id = $button.attr( 'data-like-id' );
    // создаём AJAX запрос на сервер
    jQuery.ajax( {
      type: 'GET',
      url: ThemeLiked.ajaxurl,
      data: {
        action: 'liked',
        security: ThemeLiked.liked,
        post_id: post_id,
        client_id: client_id,
      },
      // перед отправкой запроса добавляем класс для индикации загрузки
      beforeSend: function () {
        $button.addClass( 'loading' );
      },
      // действия в случае успешного запроса
      success: function ( answer ) {
        if ( answer.data.action == 'add' ) {
          liked[ liked.length ] = Number( post_id );
          $button.addClass( 'liked' );
        } else {
          liked.splice( liked.indexOf( Number( post_id ) ), 1 );
          $button.removeClass( 'liked' );
        }
        $button.attr( 'data-liked-count', answer.data.count );
      },
      error: function ( answer ) {
        console.log( answer );
      },
    // после обработки запроса убираем класс индикации загрузки
    } ).then( function () {
      window.localStorage.setItem( 'liked', JSON.stringify( liked ) );
      $button.removeClass( 'loading' );
    } );
  }

  // функция для формирования хеш-кода
  String.prototype.hashCode = function() {
    var hash = 0, i, chr;
    if ( this.length === 0) return hash;
    for (i = 0; i < this.length; i++) {
      chr   = this.charCodeAt(i);
      hash  = ( (hash << 5 ) - hash ) + chr;
      hash |= 0; // Convert to 32bit integer
    }
    return hash;
  };

  var date = new Date();
  var client_id = window.localStorage.getItem( 'client_id' );
  var liked;

  // если идентификатор клиента не задан, то формируем его
  if ( client_id == null ) {
    client_id = new String( navigator.userAgen + ' ' + date.toString() + ' ' ).hashCode();
    window.localStorage.setItem( 'client_id', client_id );
  }

  // получаем массив понравившихся постов
  if ( window.localStorage.getItem( 'liked' ) == null ) {
    liked = [];
    window.localStorage.setItem( 'liked', JSON.stringify( liked ) )
  } else {
    liked = JSON.parse( window.localStorage.getItem( 'liked' ) );
  }

  // устанавливаем статус "Понравился" выбранным кнопкам
  jQuery( '[data-like-id]' ).each( function ( index, button ) {
    var $button = jQuery( button );
    if ( liked.includes( Number( $button.attr( 'data-like-id' ) ) ) ) {
      $button.addClass( 'liked' );
      if ( $button.attr( 'data-liked-count' ).length == 0 || $button.attr( 'data-liked-count' ) == 0 ) {
        set_like( $button );
      }
    }
  } );

  // утановка событие на клик по кнопкам "Нравится"
  jQuery( 'body' ).on( 'click', '[data-like-id]:not( .loading )', function ( e ) {
    e.preventDefault();
    set_like( jQuery( this ) );    
  } );

} );

Стильове оформлення

Кнопка “Подобається” може знаходитися в трьох станах, це: “лайк не поставлений” (немає класу), “передача даних на сервер” (.loading) і “лайк поставлений” (.liked). Стан візуалізуються за допомогою класів, які додає JavaScript код. Для классу .liked використано css-анімацію.

У всіх трьох класах використовуються svg-іконки, для їх підбору зручно використовувати сервіс FlatIcon. Щоб уникнути збільшення часу завантаження при скачуванні додаткових файлів і кешувати іконки разом з іншим css кодом, іконки конвертовані в BASE64 і додані в css як текст.

@keyframes like-loading {
  from {
    transform: rotate( 0deg );
  }
  to {
    transform: rotate( 350deg );
  }
}

.like {

  display: inline-block;
  border: none;
  background-color: transparent;

  &::before {
    content: '';
    width: 1em;
    height: 1em;
    background-position: center center;
    background-repeat: no-repeat;
    background-size: contain;
    max-width: 512px;
    max-height: 512px;
    background-image: url( 'data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIC0yOCA1MTIuMDAxIDUxMiIgd2lkdGg9IjUxMnB4IiBoZWlnaHQ9IjUxMnB4Ij48cGF0aCBkPSJtMjU2IDQ1NS41MTU2MjVjLTcuMjg5MDYyIDAtMTQuMzE2NDA2LTIuNjQwNjI1LTE5Ljc5Mjk2OS03LjQzNzUtMjAuNjgzNTkzLTE4LjA4NTkzNy00MC42MjUtMzUuMDgyMDMxLTU4LjIxODc1LTUwLjA3NDIxOWwtLjA4OTg0My0uMDc4MTI1Yy01MS41ODIwMzItNDMuOTU3MDMxLTk2LjEyNS04MS45MTc5NjktMTI3LjExNzE4OC0xMTkuMzEyNS0zNC42NDQ1MzEtNDEuODA0Njg3LTUwLjc4MTI1LTgxLjQ0MTQwNi01MC43ODEyNS0xMjQuNzQyMTg3IDAtNDIuMDcwMzEzIDE0LjQyNTc4MS04MC44ODI4MTMgNDAuNjE3MTg4LTEwOS4yOTI5NjkgMjYuNTAzOTA2LTI4Ljc0NjA5NCA2Mi44NzEwOTMtNDQuNTc4MTI1IDEwMi40MTQwNjItNDQuNTc4MTI1IDI5LjU1NDY4OCAwIDU2LjYyMTA5NCA5LjM0Mzc1IDgwLjQ0NTMxMiAyNy43Njk1MzEgMTIuMDIzNDM4IDkuMzAwNzgxIDIyLjkyMTg3NiAyMC42ODM1OTQgMzIuNTIzNDM4IDMzLjk2MDkzOCA5LjYwNTQ2OS0xMy4yNzczNDQgMjAuNS0yNC42NjAxNTcgMzIuNTI3MzQ0LTMzLjk2MDkzOCAyMy44MjQyMTgtMTguNDI1NzgxIDUwLjg5MDYyNS0yNy43Njk1MzEgODAuNDQ1MzEyLTI3Ljc2OTUzMSAzOS41MzkwNjMgMCA3NS45MTAxNTYgMTUuODMyMDMxIDEwMi40MTQwNjMgNDQuNTc4MTI1IDI2LjE5MTQwNiAyOC40MTAxNTYgNDAuNjEzMjgxIDY3LjIyMjY1NiA0MC42MTMyODEgMTA5LjI5Mjk2OSAwIDQzLjMwMDc4MS0xNi4xMzI4MTIgODIuOTM3NS01MC43NzczNDQgMTI0LjczODI4MS0zMC45OTIxODcgMzcuMzk4NDM3LTc1LjUzMTI1IDc1LjM1NTQ2OS0xMjcuMTA1NDY4IDExOS4zMDg1OTQtMTcuNjI1IDE1LjAxNTYyNS0zNy41OTc2NTcgMzIuMDM5MDYyLTU4LjMyODEyNiA1MC4xNjc5NjktNS40NzI2NTYgNC43ODkwNjItMTIuNTAzOTA2IDcuNDI5Njg3LTE5Ljc4OTA2MiA3LjQyOTY4N3ptLTExMi45Njg3NS00MjUuNTIzNDM3Yy0zMS4wNjY0MDYgMC01OS42MDU0NjkgMTIuMzk4NDM3LTgwLjM2NzE4OCAzNC45MTQwNjItMjEuMDcwMzEyIDIyLjg1NTQ2OS0zMi42NzU3ODEgNTQuNDQ5MjE5LTMyLjY3NTc4MSA4OC45NjQ4NDQgMCAzNi40MTc5NjggMTMuNTM1MTU3IDY4Ljk4ODI4MSA0My44ODI4MTMgMTA1LjYwNTQ2OCAyOS4zMzIwMzEgMzUuMzk0NTMyIDcyLjk2MDkzNyA3Mi41NzQyMTkgMTIzLjQ3NjU2MiAxMTUuNjI1bC4wOTM3NS4wNzgxMjZjMTcuNjYwMTU2IDE1LjA1MDc4MSAzNy42Nzk2ODggMzIuMTEzMjgxIDU4LjUxNTYyNSA1MC4zMzIwMzEgMjAuOTYwOTM4LTE4LjI1MzkwNyA0MS4wMTE3MTktMzUuMzQzNzUgNTguNzA3MDMxLTUwLjQxNzk2OSA1MC41MTE3MTktNDMuMDUwNzgxIDk0LjEzNjcxOS04MC4yMjI2NTYgMTIzLjQ2ODc1LTExNS42MTcxODggMzAuMzQzNzUtMzYuNjE3MTg3IDQzLjg3ODkwNy02OS4xODc1IDQzLjg3ODkwNy0xMDUuNjA1NDY4IDAtMzQuNTE1NjI1LTExLjYwNTQ2OS02Ni4xMDkzNzUtMzIuNjc1NzgxLTg4Ljk2NDg0NC0yMC43NTc4MTMtMjIuNTE1NjI1LTQ5LjMwMDc4Mi0zNC45MTQwNjItODAuMzYzMjgyLTM0LjkxNDA2Mi0yMi43NTc4MTIgMC00My42NTIzNDQgNy4yMzQzNzQtNjIuMTAxNTYyIDIxLjUtMTYuNDQxNDA2IDEyLjcxODc1LTI3Ljg5NDUzMiAyOC43OTY4NzQtMzQuNjA5Mzc1IDQwLjA0Njg3NC0zLjQ1MzEyNSA1Ljc4NTE1Ny05LjUzMTI1IDkuMjM4MjgyLTE2LjI2MTcxOSA5LjIzODI4MnMtMTIuODA4NTk0LTMuNDUzMTI1LTE2LjI2MTcxOS05LjIzODI4MmMtNi43MTA5MzctMTEuMjUtMTguMTY0MDYyLTI3LjMyODEyNC0zNC42MDkzNzUtNDAuMDQ2ODc0LTE4LjQ0OTIxOC0xNC4yNjU2MjYtMzkuMzQzNzUtMjEuNS02Mi4wOTc2NTYtMjEuNXptMCAwIiBmaWxsPSIjMDAwMDAwIi8+PC9zdmc+Cg==' );
    width: 1.25em;
    height: 1.25em;
    display: inline-block;
    vertical-align: middle;
    opacity: .5;
    transition: transform .2s;
  }

  &:hover::before {
    transform: scale( 1.2 );
  }

  &.liked::before {
    background-image: url( 'data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIC0yOCA1MTIuMDAwMDEgNTEyIiB3aWR0aD0iNTEycHgiIGhlaWdodD0iNTEycHgiPjxwYXRoIGQ9Im01MTIgMTUzLjg2NzE4OGMwIDQzLjI5Mjk2OC0xNi4xMzI4MTIgODIuOTQxNDA2LTUwLjc3MzQzOCAxMjQuNzM0Mzc0LTMwLjk5NjA5MyAzNy4zOTg0MzgtNzUuNTMxMjUgNzUuMzU1NDY5LTEyNy4xMTMyODEgMTE5LjMwODU5NC0xNy42MjUgMTUuMDE1NjI1LTM3LjU5NzY1NiAzMi4wMzkwNjMtNTguMzIwMzEyIDUwLjE3MTg3NS01LjQyOTY4OCA0Ljc1LTEyLjM4NjcxOSA3LjM4NjcxOS0xOS42MTMyODEgNy40Mjk2ODhoLS4xNzk2ODhjLTcuMjg5MDYyIDAtMTQuMzE2NDA2LTIuNjQwNjI1LTE5Ljc5Mjk2OS03LjQzNzUtMjAuNjgzNTkzLTE4LjA4NTkzOC00MC42MjUtMzUuMDg5ODQ0LTU4LjIxODc1LTUwLjA4NTkzOGwtLjA4OTg0My0uMDY2NDA2Yy01MS41NzQyMTktNDMuOTU3MDMxLTk2LjEyODkwNy04MS45MjE4NzUtMTI3LjExNzE4OC0xMTkuMzIwMzEzLTM0LjY0ODQzOC00MS43OTI5NjgtNTAuNzgxMjUtODEuNDQxNDA2LTUwLjc4MTI1LTEyNC43MzQzNzQgMC00Mi4wNjY0MDcgMTQuNDI1NzgxLTgwLjg4MjgxMyA0MC42MTcxODgtMTA5LjI5Mjk2OSAyNi41MDc4MTItMjguNzUgNjIuODc1LTQ0LjU3NDIxOSAxMDIuNDE0MDYyLTQ0LjU3NDIxOSAyOS41NTg1OTQgMCA1Ni42MTcxODggOS4zMzU5MzggODAuNDQ5MjE5IDI3Ljc2MTcxOSAxMi4wMjczNDMgOS4zMDQ2ODcgMjIuOTIxODc1IDIwLjY3OTY4NyAzMi41MTk1MzEgMzMuOTY0ODQzbC4xNzk2ODgtLjIzODI4MWM5LjU1ODU5My0xMy4xODM1OTMgMjAuMzk0NTMxLTI0LjQ4MDQ2OSAzMi4zNDc2NTYtMzMuNzI2NTYyIDIzLjgyNDIxOC0xOC40MjU3ODEgNTAuODk0NTMxLTI3Ljc2MTcxOSA4MC40NDE0MDYtMjcuNzYxNzE5IDM5LjU0Njg3NSAwIDc1LjkxNDA2MiAxNS44MjQyMTkgMTAyLjQxNDA2MiA0NC41NzQyMTkgMjYuMTkxNDA3IDI4LjQxMDE1NiA0MC42MTcxODggNjcuMjE0ODQzIDQwLjYxNzE4OCAxMDkuMjkyOTY5em0wIDAiIGZpbGw9IiNmZjVlOTUiLz48cGF0aCBkPSJtNTEyIDE1My44NjcxODhjMCA0My4yOTI5NjgtMTYuMTMyODEyIDgyLjk0MTQwNi01MC43NzM0MzggMTI0LjczNDM3NC0zMC45OTYwOTMgMzcuMzk4NDM4LTc1LjUzMTI1IDc1LjM1NTQ2OS0xMjcuMTEzMjgxIDExOS4zMDg1OTQtMTcuNjI1IDE1LjAxNTYyNS0zNy41OTc2NTYgMzIuMDM5MDYzLTU4LjMyMDMxMiA1MC4xNzE4NzUtNS40Mjk2ODggNC43NS0xMi4zODY3MTkgNy4zODY3MTktMTkuNjEzMjgxIDcuNDI5Njg4di0zOTQuMDIzNDM4YzkuNTU4NTkzLTEzLjE4MzU5MyAyMC4zOTQ1MzEtMjQuNDgwNDY5IDMyLjM0NzY1Ni0zMy43MjY1NjIgMjMuODI0MjE4LTE4LjQyNTc4MSA1MC44OTQ1MzEtMjcuNzYxNzE5IDgwLjQ0MTQwNi0yNy43NjE3MTkgMzkuNTQ2ODc1IDAgNzUuOTE0MDYyIDE1LjgyNDIxOSAxMDIuNDE0MDYyIDQ0LjU3NDIxOSAyNi4xOTE0MDcgMjguNDEwMTU2IDQwLjYxNzE4OCA2Ny4yMTQ4NDMgNDAuNjE3MTg4IDEwOS4yOTI5Njl6bTAgMCIgZmlsbD0iI2ZmMzk4MCIvPjwvc3ZnPgo=' );
    opacity: 1;
  }

  &::after {
    content: attr( data-liked-count );
    margin-left: .25em;
    color: #000;
  }

  &.loading::after {
    content: '';
    width: 1em;
    height: 1em;
    background-position: center center;
    background-repeat: no-repeat;
    background-size: contain;
    max-width: 512px;
    max-height: 512px;
    width: 1em;
    height: 1em;
    display: inline-block;
    vertical-align: middle;
    transform-origin: center center;
    animation-name: like-loading;
    animation-duration: 1s;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
    animation-fill-mode: backwards;
    background-image: url( 'data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjUxMnB4IiBoZWlnaHQ9IjUxMnB4IiB2aWV3Qm94PSIwIDAgMzQ0LjM3IDM0NC4zNyIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMzQ0LjM3IDM0NC4zNzsiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8Zz4KCTxnPgoJCTxwYXRoIGQ9Ik0zMzQuNDg1LDM3LjQ2M2MtNi43NTMtMS40NDktMTMuMzk2LDIuODUzLTE0Ljg0Miw5LjYwM2wtOS4wODQsNDIuMzkxQzI4MS42MzcsNDAuMTE3LDIyOC41NTEsOS4xNTUsMTcwLjM2OCw5LjE1NSAgICBjLTg5LjYwMywwLTE2Mi41LDcyLjg5Ni0xNjIuNSwxNjIuNWMwLDYuOTAzLDUuNTk2LDEyLjUsMTIuNSwxMi41YzYuOTAzLDAsMTIuNS01LjU5NywxMi41LTEyLjUgICAgYzAtNzUuODE4LDYxLjY4Mi0xMzcuNSwxMzcuNS0xMzcuNWM0OS40MjksMCw5NC41MTUsMjYuNDAzLDExOC45MjUsNjguNDQzbC00MS42NzQtOC45MzFjLTYuNzUyLTEuNDQ3LTEzLjM5NiwyLjg1NC0xNC44NDEsOS42MDQgICAgYy0xLjQ0Niw2Ljc1LDIuODU0LDEzLjM5Niw5LjYwNCwxNC44NDJsNzEuNTM2LDE1LjMzYzEuMjE1LDAuMjYxLDIuNDQ5LDAuMzM2LDMuNjY2LDAuMjM0YzIuMDI3LTAuMTcxLDQuMDAzLTAuODM2LDUuNzQzLTEuOTYyICAgIGMyLjc4NC0xLjgwMSw0LjczOC00LjYzNCw1LjQzMy03Ljg3NWwxNS4zMzEtNzEuNTM2QzM0NS41MzUsNDUuNTU1LDM0MS4yMzUsMzguOTExLDMzNC40ODUsMzcuNDYzeiIgZmlsbD0iIzAwMDAwMCIvPgoJCTxwYXRoIGQ9Ik0zMjEuOTA3LDE1NS4yNzFjLTYuODk5LDAuMjI4LTEyLjMwOSw2LjAwNi0xMi4wODEsMTIuOTA1YzEuMjEyLDM2LjcwOC0xMS45NDIsNzEuNjg5LTM3LjA0Miw5OC41MDQgICAgYy0yNS4wOTksMjYuODEyLTU5LjEzNyw0Mi4yNDgtOTUuODQ0LDQzLjQ2Yy0xLjUzLDAuMDUtMy4wNTIsMC4wNzUtNC41NzYsMC4wNzVjLTQ3Ljg5Ni0wLjAwMi05Mi4wMTgtMjQuODc3LTExNi45MzYtNjUuMTggICAgbDQzLjQ0NywxMS42NWM2LjY2OCwxLjc4NywxMy41MjMtMi4xNjgsMTUuMzExLTguODM3YzEuNzg4LTYuNjY4LTIuMTY4LTEzLjUyMi04LjgzNi0xNS4zMTJsLTcwLjY2NC0xOC45NDYgICAgYy0zLjIwMi0wLjg1Ny02LjYxNS0wLjQwOS05LjQ4NSwxLjI0N2MtMi44NzIsMS42NTYtNC45NjcsNC4zODctNS44MjYsNy41ODlMMC40MywyOTMuMDkyICAgIGMtMS43ODgsNi42NjgsMi4xNjgsMTMuNTIyLDguODM2LDE1LjMxMWMxLjA4NSwwLjI5MSwyLjE3MywwLjQzMSwzLjI0NSwwLjQzMWM1LjUxOCwwLDEwLjU2OS0zLjY4NCwxMi4wNjYtOS4yNjdsMTAuNjQ5LTM5LjcxNyAgICBjMjkuNjI0LDQ2LjY0Nyw4MS4xODksNzUuMzY3LDEzNy4xMzIsNzUuMzY1YzEuNzk3LDAsMy42MDQtMC4wMjksNS40MDgtMC4wODljNDMuMzgxLTEuNDM0LDgzLjYwOC0xOS42NzQsMTEzLjI3MS01MS4zNjIgICAgczQ1LjIwOS03My4wMzEsNDMuNzc2LTExNi40MTNDMzM0LjU4NiwxNjAuNDUzLDMyOC44MDUsMTU1LjAyNiwzMjEuOTA3LDE1NS4yNzF6IiBmaWxsPSIjMDAwMDAwIi8+Cgk8L2c+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPC9zdmc+Cg==' );
  }

}

Висновок

Цей метод дуже простий, але не позбавлений недоліків пов’язаних з можливістю накрутки, при бажанні це можна виправити і вдосконалити його. А саме:

  • додати віджет або шорткод з вибіркою популярних потів;
  • поліпшити захист від накрутки;
  • для ідентифікації користувачів використовувати скрипт google-аналітики;
  • на основі масиву ідентифікаторів вподобаних постів сформувати список обраного

Під час розробки WordPress-теми таку кнопку легко додати як «дефолтну», а згодом і при необхідності замінити на більш просунутий функціонал. Варіантів безліч.

Git-проект: https://github.com/chomovva/wp-simple-likes

голос
Рейтинг статті
Підписатися
Сповістити про
guest
0 Коментарі
Вбудовані Відгуки
Переглянути всі коментарі
0
Ми любимо ваші думки, будь ласка, прокоментуйте.x
()
x