strokoff

Интегрируем веб-компонент wc-likes в wordpress


В этой статье мы рассмотрим вариант интеграции веб-компонента wc-likes с CMS системой wordpress на примере сайта webislife.ru

В этой статье я не буду рассматривать вариант установки, компонент настолько маленький, что его можно скопировать прост в проект ну или поддерживать последнюю актуальную версию wc-likes из npm. У нас он просто уже есть и нам нужно его интегрировать в wordpress и обойтись без новых зависимостей в фреймворках и плагинах. Конечно же вы можете скачать и просто установить плагин для wordpress, может даже я сделаю когда-нибудь его отдельно, но сегодня речь пойдет о интеграции технологии через код и поддержку самой темой webislife для wp c лайками

Добавляем лайки в wordpress

Изначально wordpress не поддерживает понятие и модель лайков, их можно добавить через post meta fields, но мы пойдем еще более нативным путем, создаем таблицу в бд wordpress отдельно для хранения лайков, использование своей таблицы даст нам преимущества в скорости работы сайта и независимости от механик wordpress, код который создаст таблицу для лайков постов может выглядеть вот так

$table_name = $wpdb->prefix . "wp_post_likes"; 
$charset_collate = $wpdb->get_charset_collate();

$sql = "CREATE TABLE $table_name (
  id mediumint(9) NOT NULL AUTO_INCREMENT,
  ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  post_id mediumint(9) NOT NULL,
  user_id mediumint(9) NOT NULL,
  PRIMARY KEY  (id)
) $charset_collate;";

require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
dbDelta( $sql );

Отлично, осталось добавить еще пару php функций в наш function.php для реализации API методов добавления и получения лайков

Получаем лайки из бд

//Получаем лайки из бд
function WC_LIKES_GET_BYPOST($req) {
    $response_data = array( 
        'success' => true,
        'count' => 0,
        'code' => 200,
    );
    
    $reqjson = json_decode($req->get_body(), true);
    $post_id = intval($reqjson['post_id']);
    //required post id
    if(is_int($post_id) === false) {
        $response_data['error'] = 'post_id:number required';
        $response = new WP_REST_Response( $response_data );
        $response->set_status( 200 );
        return $response;
    }
    global $wpdb;
    $sql = $wpdb->get_row("SELECT COUNT(id) as count FROM `wp_post_likes` WHERE post_id=".$post_id);
    $response_data['count'] = $sql->count;
    $response = new WP_REST_Response( $response_data );
    $response->set_status( 200 );
    return $response;
}
/**
 * Отправка лайка с сайта
 * API POST /wp-json/wlapi/v1/post
 */
function WC_LIKES_POST($request) {
    $response_data = array( 
        'success' => true,
        'error' => '',
        'code' => 200,
    );
    $reqjson = json_decode($request->get_body(), true);
    $post_id = intval($reqjson['post_id']);
    $user_id = get_current_user_id($token);
    $response_data['post_id'] = $post_id;
    $headers = $request->get_headers();
    //required post id
    if(is_int($post_id) === false) {
        $response_data['error'] = 'post_id:number required';
        $response = new WP_REST_Response( $response_data );
        $response->set_status( 200 );
        return $response;
    }
    //post need exist
    $like_post = get_post($post_id);
    if(is_null($like_post)) {
        $response_data['error'] = "post id:".$reqjson['post_id'].' - not found';
        $response = new WP_REST_Response( $response_data );
        $response->set_status( 200 );
        return $response;
    }
    //auth user
    if($user_id === 0) {
        $response_data['error'] = "auth require";
        $response_data['code'] = 401;
        $response = new WP_REST_Response( $response_data );
        $response->set_status( 200 );
        return $response;
    }
    global $wpdb;
    $user_count = $wpdb->get_row("SELECT COUNT(id) as count FROM `wp_post_likes` WHERE user_id=".$user_id." AND post_id=".$post_id)->count;
    if($user_count > 0) {
        $response_data['error'] = "alreadyVoted";
        $response_data['success'] = false;
        $response_data['code'] = 200;
        $response = new WP_REST_Response( $response_data );
        $response->set_status( 200 );
        return $response;
    }
    //insert like 
    // $sql = $wpdb->query( "INSERT INTO `wp_post_likes` (`post_id`, `user_id`) VALUES (".$post_id.", ".$user_id.")" );
    $sql = $wpdb->insert( "wp_post_likes", [ 'post_id' => $post_id, 'user_id' => $user_id ] );

    $response_data['user_id'] = $user_id;
    // $response_data['result'] = "INSERT INTO `wp_post_likes` (`post_id`, `user_id`) VALUES (".$post_id.", ".$user_id.")";
    $response_data['sql'] = $sql;
    $response_data['success'] = true;
    $response = new WP_REST_Response( $response_data );
    $response->set_status( 200 );
    return $response;
}

Осталось добавить поддержку REST API через следующим образом

add_action( 'rest_api_init', function () {
    register_rest_route( 'wlapi', '/OG/', array(
      'methods' => 'GET',
      'callback' => 'API_OG',
    ) );
    // API WC-likes section
    register_rest_route( 'wlapi', '/wc-likes/post', array(
        'methods' => 'POST',
        'callback' => 'WC_LIKES_POST',
      ) );
    register_rest_route( 'wlapi', '/wc-likes/get-by-post', array(
        'methods' => 'POST',
        'callback' => 'WC_LIKES_GET_BYPOST',
    ) );
  } );

С бекенд частью закончили, просто не так ли? Этим и подкупает разработка на wordpress)

Переиспользуем веб-компонент wc-likes

Основная реализация и стили лайков уже заложены в компоненте wc-likes, осталось лишь добавить поддержку наших созданных апишек на фронте, давайте расширим wc-likes

import WCLikes from './web/wc-like.js';
import WPA from './../app.js';

class WCLikesPost extends WCLikes {
    
    initialState:WPA["State"]

    constructor() {
        super();
    }

    connectedCallback(): void {
        this.fetchAsyncLikes();
        const initialState:WPA["State"] = window.__WPA.State;
        if(initialState.userLogged === false) {
            this.classList.add('-auth');
            this.setAttribute('data-hint', 'Для лайков необходимо авторизоваться');
            this.LikesIcon.onpointerup = null;
        }
    }
    /**
     * Submit post like
     */
    async fetchSubmitLikes():Promise {
        const post_id = +this.getAttribute('data-post-id');
        const likesCountResponseJson = await window._WPA.API('/wp-json/wlapi/wc-likes/post', {
            method: 'POST',
            body: JSON.stringify({post_id})
        }, true, true);
        if(likesCountResponseJson.error === 'alreadyVoted' && likesCountResponseJson.success == false) {
            this.Liked = true;
            this.setAttribute('data-hint', 'Вы уже лайкали этот пост');
            
        }
        return likesCountResponseJson.success === true ? 200 : likesCountResponseJson.code;
    }

    /**
     * Fetch likes count
     */
    async fetchAsyncLikes(params?:any):Promise {
        this.setAttribute('fetch', '1');
        const post_id = +this.getAttribute('data-post-id')
        const likesCountResponseJson = await window._WPA.API('/wp-json/wlapi/wc-likes/get-by-post', {
            method: 'POST',
            body: JSON.stringify({post_id})
        }, true);
        this.removeAttribute('fetch');
        this.setAttribute('value', likesCountResponseJson.count);
        return likesCountResponseJson.count;
    }
}
window.customElements.define('wc-likes-post', WCLikesPost);
export default WCLikesPost;

Все очень просто, мы расширили класс компонента wc-likes и реализовали в нем 2 метода отправки и получения лайков
fetchSubmitLikes и fetchAsyncLikes в итоге нам не пришолсь писать ни капли boilerplate кода. Осталось вывести в шаблоне сайта наши лайки например в single-post.php шаблоне

<wc-likes-post class="-fetch" data-post-id="<?=$post_id;?>" data-logged="<?=$isLoggedIn;?>"></wc-likes-post>

Зарегистрируйтесь, чтобы проверить работу лайка прямо под этим постом)

p.s. Критика и доработки от разработчиков специализирующиеся на php и wordpress приветствуется, давайте вместе делать web лучше)

Последняя редакция 8 февраля, 2023 в 12:02