Статьи

Как создать свой собственный плагин AJAX WooCommerce Wishlist

В этом уроке мы создадим функциональность облегченного списка желаний для WooCommerce, используя AJAX, WordPress REST API и графику SVG. WooCommerce не входит в стандартную функциональность списка желаний, поэтому вам всегда нужно полагаться на расширение, которое сделает всю работу за вас. Если вы не построите это сами для полного контроля ..

Функциональность Wishlist позволит пользователям отмечать определенные продукты, добавляя их в список для дальнейшего использования. В некоторых магазинах электронной коммерции (таких как Amazon) можно создать несколько списков желаний, которые можно использовать совместно с другими, что делает их идеальными для дней рождения или свадеб. В нашем случае, список пожеланий WooCommerce, который мы собираемся создать, позволит клиентам легко просматривать продукты, которые они рассматривают.

Наша функциональность списка пожеланий добавит значок сердца к превью товара, который при нажатии добавит товар в список желаний в таблице.

WooCommerce решение для списка пожеланий
Нажмите значок сердца, чтобы добавить продукт в список желаний

Взгляните на демо-версию, чтобы понять, как она работает.

Давайте начнем с создания нашего плагина. Создайте папку с именем «wishlist» и файл PHP с тем же именем. Добавьте следующий фрагмент в файл PHP:

01
02
03
04
05
06
07
08
09
10
11
12
/*
    Plugin Name: Woocommerce wishlist
    Plugin URI: https://www.enovathemes.com
    Description: Ajax wishlist for WooCommerce
    Author: Enovathemes
    Version: 1.0
    Author URI: http://enovathemes.com
*/
 
if ( ! defined( ‘ABSPATH’ ) ) {
    exit;
}

Мы не будем вдаваться в подробности процесса создания плагинов, но если вы новичок в разработке плагинов, я настоятельно рекомендую этот удивительный новый курс Рэйчел Макколлин:

  • WordPress
    Введение в разработку плагинов WordPress
    Рэйчел Макколлин

Давайте наметим наш план, чтобы мы знали, что строить:

  • Добавьте список желаний для товаров в цикле и на отдельных страницах, используя хуки WooCommerce
  • Создать шорткод таблицы пожеланий для хранения товаров, добавленных в список желаний
  • Создать пользовательскую опцию в списке желаний в профиле пользователя

Весь код плагина будет находиться внутри действия init для плагина, так как сначала нам нужно убедиться, что плагин WooCommerce активен. Поэтому сразу после деталей плагина добавьте следующий код:

1
2
3
4
5
6
add_action(‘init’,’plugin_init’);
function plugin_init(){
    if (class_exists(«Woocommerce»)) {
    // Code here
    }
}

А теперь давайте поставим в очередь наши скрипты и стили плагинов.

Добавьте следующий код в основной файл плагина:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
function wishlist_plugin_scripts_styles(){
    wp_enqueue_style( ‘wishlist-style’, plugins_url(‘/css/style.css’, __FILE__ ), array(), ‘1.0.0’ );
    wp_enqueue_script( ‘wishlist-main’, plugins_url(‘/js/main.js’, __FILE__ ), array(‘jquery’), », true);
    wp_localize_script(
        ‘main’,
        ‘opt’,
        array(
            ‘ajaxUrl’ => admin_url(‘admin-ajax.php’),
            ‘ajaxPost’ => admin_url(‘admin-post.php’),
            ‘restUrl’ => rest_url(‘wp/v2/product’),
            ‘shopName’ => sanitize_title_with_dashes(sanitize_title_with_dashes(get_bloginfo(‘name’))),
            ‘inWishlist’ => esc_html__(«Already in wishlist»,»text-domain»),
            ‘removeWishlist’ => esc_html__(«Remove from wishlist»,»text-domain»),
            ‘buttonText’ => esc_html__(«Details»,»text-domain»),
            ‘error’ => esc_html__(«Something went wrong, could not add to wishlist»,»text-domain»),
            ‘noWishlist’ => esc_html__(«No wishlist found»,»text-domain»),
        )
    );
}
add_action( ‘wp_enqueue_scripts’, ‘wishlist_plugin_scripts_styles’ );

Здесь мы ставим в очередь основной файл style.css и файл main.js для плагина, а также передаем некоторые параметры в файл main.js для работы:

  • ajaxUrl — требуется для извлечения некоторых данных из WordPress, например, текущего идентификатора пользователя
  • ajaxPost — требуется обновить список пожеланий пользователя
  • restUrl — требуется перечислить элементы списка желаний в таблице желаний
  • shopName — требуется добавить элементы shopName желаний в хранилище сеансов для незарегистрированных или не вошедших в систему пользователей

И некоторые строки вместо жесткого кодирования их в файл js, на случай, если они должны быть переведены.

Поэтому сейчас создайте папки css и js и поместите соответствующие файлы в эти папки: style.css в папке css и main.js в папке js .

Прямо внутри действия init добавьте следующий код:

1
2
3
4
5
6
7
8
// Add wishlist to product
add_action(‘woocommerce_before_shop_loop_item_title’,’wishlist_toggle’,15);
add_action(‘woocommerce_single_product_summary’,’wishlist_toggle’,25);
function wishlist_toggle(){
 
    global $product;
    echo ‘<span class=»wishlist-title»>’.esc_attr__(«Add to wishlist»,»text-domain»).’
}

Здесь мы добавляем список желаний для каждого продукта в цикле и для каждого отдельного макета продукта, используя woocommerce_before_shop_loop_item_title и woocommerce_single_product_summary .

Здесь я хочу указать на атрибут data-product который содержит ID продукта — это необходимо для включения функциональности списка желаний. А также более внимательно посмотрите на значок SVG — это необходимо для включения анимации.

Теперь создайте папку с изображениями в папке плагина и поместите в нее следующий файл icon.svg:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<svg viewBox=»0 0 471.701 471.701″>
    <path class=»heart» d=»M433.601,67.001c-24.7-24.7-57.4-38.2-92.3-38.2s-67.7,13.6-92.4,38.3l-12.9,12.9l-13.1-13.1
            c-24.7-24.7-57.6-38.4-92.5-38.4c-34.8,0-67.6,13.6-92.2,38.2c-24.7,24.7-38.3,57.5-38.2,92.4c0,34.9,13.7,67.6,38.4,92.3
            l187.8,187.8c2.6,2.6,6.1,4,9.5,4c3.4,0,6.9-1.3,9.5-3.9l188.2-187.5c24.7-24.7,38.3-57.5,38.3-92.4
            C471.801,124.501,458.301,91.701,433.601,67.001z M414.401,232.701l-178.7,178l-178.3-178.3c-19.6-19.6-30.4-45.6-30.4-73.3
            s10.7-53.7,30.3-73.2c19.5-19.5,45.5-30.3,73.1-30.3c27.7,0,53.8,10.8,73.4,30.4l22.6,22.6c5.3,5.3,13.8,5.3,19.1,0l22.4-22.4
            c19.6-19.6,45.7-30.4,73.3-30.4c27.6,0,53.6,10.8,73.2,30.3c19.6,19.6,30.3,45.6,30.3,73.3
            C444.801,187.101,434.001,213.101,414.401,232.701z»/>
    <g class=»loading»>
        <path d=»M409.6,0c-9.426,0-17.067,7.641-17.067,17.067v62.344C304.667-5.656,164.478-3.386,79.411,84.479
            c-40.09,41.409-62.455,96.818-62.344,154.454c0,9.426,7.641,17.067,17.067,17.067S51.2,248.359,51.2,238.933
            c0.021-103.682,84.088-187.717,187.771-187.696c52.657,0.01,102.888,22.135,138.442,60.976l-75.605,25.207
            c-8.954,2.979-13.799,12.652-10.82,21.606s12.652,13.799,21.606,10.82l102.4-34.133c6.99-2.328,11.697-8.88,11.674-16.247v-102.4
            C426.667,7.641,419.026,0,409.6,0z»/>
        <path d=»M443.733,221.867c-9.426,0-17.067,7.641-17.067,17.067c-0.021,103.682-84.088,187.717-187.771,187.696
            c-52.657-0.01-102.888-22.135-138.442-60.976l75.605-25.207c8.954-2.979,13.799-12.652,10.82-21.606
            c-2.979-8.954-12.652-13.799-21.606-10.82l-102.4,34.133c-6.99,2.328-11.697,8.88-11.674,16.247v102.4
            c0,9.426,7.641,17.067,17.067,17.067s17.067-7.641,17.067-17.067v-62.345c87.866,85.067,228.056,82.798,313.122-5.068
            c40.09-41.409,62.455-96.818,62.344-154.454C460.8,229.508,453.159,221.867,443.733,221.867z»/>
    </g>
    <g class=»check»>
        <path d=»M238.933,0C106.974,0,0,106.974,0,238.933s106.974,238.933,238.933,238.933s238.933-106.974,238.933-238.933
            C477.726,107.033,370.834,0.141,238.933,0z M238.933,443.733c-113.108,0-204.8-91.692-204.8-204.8s91.692-204.8,204.8-204.8
            s204.8,91.692,204.8,204.8C443.611,351.991,351.991,443.611,238.933,443.733z»/>
        <path d=»M370.046,141.534c-6.614-6.388-17.099-6.388-23.712,0v0L187.733,300.134l-56.201-56.201
            c-6.548-6.78-17.353-6.967-24.132-0.419c-6.78,6.548-6.967,17.353-0.419,24.132c0.137,0.142,0.277,0.282,0.419,0.419
            l68.267,68.267c6.664,6.663,17.468,6.663,24.132,0l170.667-170.667C377.014,158.886,376.826,148.082,370.046,141.534z»/>
    </g>
</svg>

Если вы новичок в работе с SVG, я настоятельно рекомендую вам прочитать эти удивительные учебники по этой теме:

  • SVG
    Как передать код SVG
    Кезз Брейси
  • SVG
    SVG Viewport и viewBox (для начинающих)
    Кезз Брейси

Наша анимация SVG имеет 3 состояния:

  1. По умолчанию: путь сердца
  2. Процесс: загрузка группы (тег g)
  3. Конец: проверка группы (тег g)

Если вы сейчас перейдете на страницу своего магазина, то увидите непростые значки SVG, сложенные друг на друга:

значки стиля svg

Давайте добавим немного стилей, чтобы исправить этот беспорядок! Откройте файл style.css и вставьте следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
.wishlist-toggle {
    display: block;
    position: absolute;
    top: 16px;
    left: 16px;
    z-index: 5;
    width: 24px;
    height: 24px;
    outline: none;
    border:none;
}
 
.wishlist-title {
    display: none;
}
 
.entry-summary .wishlist-toggle {
    position: relative;
    top: 0;
    left: 0;
    display: inline-block;
    vertical-align: middle;
    margin-bottom: 8px;
}
 
.entry-summary .wishlist-title {
    display: inline-block;
    vertical-align: middle;
    margin-right: 8px;
    margin-bottom: 8px;
}
 
.wishlist-toggle:focus {
    outline: none;
    border:none;
}
 
.wishlist-toggle svg {
    fill:#bdbdbd;
    transition: all 200ms ease-out;
}
 
.wishlist-toggle:hover svg,
.wishlist-toggle.active svg {
    fill:#000000;
}
 
.wishlist-toggle svg .loading,
.wishlist-toggle svg .check {
    opacity: 0;
}
 
.wishlist-toggle.active svg .check {
    opacity: 1;
}
 
.wishlist-toggle.active svg .heart {
    opacity: 0;
}
 
.wishlist-toggle.loading svg .loading,
.wishlist-table.loading:before {
    animation:loading 500ms 0ms infinite normal linear;
    transform-origin: center;
    opacity: 1;
}
 
.wishlist-toggle.loading svg .heart {
    opacity:0;
}
 
@keyframes loading {
    from {transform: rotate(0deg);}
    to {transform: rotate(360deg);}
}

Логика здесь следующая:

  1. Изначально мы показываем сердечный путь нашего SVG.
  2. Когда пользователь нажимает на него, мы скрываем путь сердца и показываем путь загрузки.
  3. После завершения загрузки мы покажем галочку, указывающую, что продукт был успешно добавлен в список желаний.

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

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

Добавьте следующий код в действие плагина init :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
// Wishlist table shortcode
add_shortcode(‘wishlist’, ‘wishlist’);
function wishlist( $atts, $content = null ) {
 
    extract(shortcode_atts(array(), $atts));
 
    return ‘<table class=»wishlist-table loading»>
                <tr>
                    <th><!— Left for image —></th>
                    <th>’.esc_html__(«Name»,»text-domain»).'</th>
                    <th>’.esc_html__(«Price»,»text-domain»).'</th>
                    <th>’.esc_html__(«Stock»,»text-domain»).'</th>
                    <th><!— Left for button —></th>
                </tr>
            </table>’;
 
}

Это очень простой шорткод, который вы можете добавить на любую страницу, и на нем появятся элементы списка желаний. Я не буду описывать процесс создания шорткода, но если вы новичок в этом, я настоятельно рекомендую прочитать этот удивительный урок:

  • Плагины
    Начало работы с шорткодами WordPress
    Рохан Мехта

Теперь внутри WP Admin создайте страницу под названием «Wishlist» и поместите в нее шорткод [wishlist] . Теперь, если вы перейдете на страницу списка желаний, вы увидите пустую таблицу.

Вы заметили класс загрузки на столе? Мы удалим класс загрузки с помощью JavaScript позже, когда элементы списка пожеланий будут готовы для добавления в таблицу. Но сейчас откройте style.css и добавьте следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
.wishlist-table {
    width:100%;
    position: relative;
}
 
.wishlist-table.loading:after {
    display: block;
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    content: «»;
    background: #ffffff;
    opacity: 0.5;
    z-index: 5;
}
 
.wishlist-table.loading:before {
    display: block;
    width: 24px;
    height: 24px;
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top:-12px;
    margin-left:-12px;
    content: «»;
    background-image: url(‘../images/loading.svg’);
    background-repeat: no-repeat;
    background-size: 100%;
    z-index: 6;
}
 
.wishlist-table td {
    position: relative;
}
 
.wishlist-table a.details {
    padding:4px 16px;
    background: #000000;
    color: #ffffff;
    text-align: center;
    border:none !important
}
 
.wishlist-table a.wishlist-remove {
    display: block;
    width: 24px;
    height: 24px;
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top:-12px;
    margin-left:-12px;
    background-image: url(‘../images/remove.svg’);
    background-repeat: no-repeat;
    background-size: 100%;
    z-index: 6;
    border:none;
    opacity:0;
}
 
.wishlist-table td:hover > a.wishlist-remove {
    opacity:1;
}

Добавьте изображение loading.svg в папку images:

01
02
03
04
05
06
07
08
09
10
11
12
<svg xmlns=»http://www.w3.org/2000/svg» xmlns:xlink=»http://www.w3.org/1999/xlink» viewBox=»0 0 471.701 471.701″>
    <path d=»M409.6,0c-9.426,0-17.067,7.641-17.067,17.067v62.344C304.667-5.656,164.478-3.386,79.411,84.479
        c-40.09,41.409-62.455,96.818-62.344,154.454c0,9.426,7.641,17.067,17.067,17.067S51.2,248.359,51.2,238.933
        c0.021-103.682,84.088-187.717,187.771-187.696c52.657,0.01,102.888,22.135,138.442,60.976l-75.605,25.207
        c-8.954,2.979-13.799,12.652-10.82,21.606s12.652,13.799,21.606,10.82l102.4-34.133c6.99-2.328,11.697-8.88,11.674-16.247v-102.4
        C426.667,7.641,419.026,0,409.6,0z»/>
    <path d=»M443.733,221.867c-9.426,0-17.067,7.641-17.067,17.067c-0.021,103.682-84.088,187.717-187.771,187.696
        c-52.657-0.01-102.888-22.135-138.442-60.976l75.605-25.207c8.954-2.979,13.799-12.652,10.82-21.606
        c-2.979-8.954-12.652-13.799-21.606-10.82l-102.4,34.133c-6.99,2.328-11.697,8.88-11.674,16.247v102.4
        c0,9.426,7.641,17.067,17.067,17.067s17.067-7.641,17.067-17.067v-62.345c87.866,85.067,228.056,82.798,313.122-5.068
        c40.09-41.409,62.455-96.818,62.344-154.454C460.8,229.508,453.159,221.867,443.733,221.867z»/>
</svg>

Это та же загрузка SVG, отделенная от основного icon.svg. Мы могли бы использовать SVG-спрайты, но я решил придерживаться отдельной загрузки SVG.

Теперь, если вы перейдете на страницу списка пожеланий и обновите ее, вы увидите пустую таблицу с загрузкой на нее. Хорошо, давайте двигаться дальше.

Функциональность нашего списка желаний будет работать как для зарегистрированных пользователей, так и для гостей. Для зарегистрированных пользователей мы будем хранить информацию о списке желаний в метаданных пользователя, а с гостевыми пользователями мы будем хранить список желаний в хранилище сеансов .

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

Теперь добавьте следующий код в действие init :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
// Wishlist option in the user profile
add_action( ‘show_user_profile’, ‘wishlist_user_profile_field’ );
add_action( ‘edit_user_profile’, ‘wishlist_user_profile_field’ );
function wishlist_user_profile_field( $user ) { ?>
    <table class=»form-table wishlist-data»>
        <tr>
            <th><?php echo esc_attr__(«Wishlist»,»text-domain»);
            <td>
                <input type=»text» name=»wishlist» id=»wishlist» value=»<?php echo esc_attr( get_the_author_meta( ‘wishlist’, $user->ID ) ); ?>» class=»regular-text» />
            </td>
        </tr>
    </table>
<?php }
 
add_action( ‘personal_options_update’, ‘save_wishlist_user_profile_field’ );
add_action( ‘edit_user_profile_update’, ‘save_wishlist_user_profile_field’ );
function save_wishlist_user_profile_field( $user_id ) {
    if ( !current_user_can( ‘edit_user’, $user_id ) ) {
        return false;
    }
    update_user_meta( $user_id, ‘wishlist’, $_POST[‘wishlist’] );
}

Опять же, чтобы оставаться в рамках этого урока, я не буду объяснять, как работать с метаданными пользователя. Если вы новичок в этом, я настоятельно рекомендую прочитать этот удивительный урок:

  • WordPress
    Как работать с метаданными пользователя WordPress
    Том Макфарлин

Все, что мы здесь делаем, — это создаем ввод текстового поля, в котором будут храниться элементы списка пожеланий, разделенные запятыми. С show_user_profile действий show_user_profile и edit_user_profile мы добавляем структуру поля ввода, а с edit_user_profile_update действий personal_options_update и edit_user_profile_update функцию сохранения.

Таким образом, после обновления списка пожеланий он будет сохранен в базе данных. Если вы перейдете на страницу своего профиля, вы увидите новое текстовое поле, добавленное к нему. Добавьте любое значение и нажмите « Сохранить», чтобы проверить, работает ли функция обновления. С помощью CSS администратора вы можете скрыть это поле, если вы не хотите, чтобы пользователи видели его. Я оставлю это как есть.

Теперь мы готовы включить все!

Откройте файл main.js и поместите в него следующий код:

1
2
3
(function($){
    «use strict»;
})(jQuery);

Весь наш код будет идти внутри этой функции.

Теперь давайте соберем необходимые данные и создадим несколько переменных:

1
2
3
4
5
6
7
var shopName = opt.shopName+’-wishlist’,
   inWishlist = opt.inWishlist,
   restUrl = opt.restUrl,
   wishlist = new Array,
   ls = sessionStorage.getItem(shopName),
   loggedIn = ($(‘body’).hasClass(‘logged-in’)) ?
   userData = »;

Как вы, наверное, помните, когда мы ставили в очередь наш скрипт main.js, мы передавали ему некоторые параметры. Здесь, с помощью JavaScript, мы можем собрать эти параметры.

Далее мы создадим пустой массив списков пожеланий, который будет содержать элементы списка желаний. Нам понадобятся данные хранилища сессий с названием нашего магазина (переменная ls обозначает локальное хранилище ), и нам нужно будет знать, является ли пользователь гостем или вошел в систему.

Позвольте мне объяснить здесь логику: всякий раз, когда пользователь посещает страницу магазина, нам нужно знать, вошел ли он в систему или является гостем. Если пользователь вошел в систему, нам нужно проверить, есть ли у него элементы списка желаний, и если это так, выделите эти элементы. Если нет, нам нужно посмотреть, есть ли какие-либо элементы в сессионном / локальном хранилище и выделить их.

Почему это делается так? Представьте, если пользователь сначала заходит на сайт как гость, добавляет элементы в список желаний, а затем решает войти в систему. Если у пользователя нет элементов, зарегистрированных в списке пожеланий профиля, нам нужно будет показать те, которые он или она добавили до входа в систему, которые хранятся в сеансе / локальном хранилище.

Итак, давайте сделаем это шаг за шагом:

  • Получить текущие данные пользователя с AJAX
  • В случае успеха обновите список желаний
  • Выделите элементы списка желаний
  • Удалить сеанс / локальное хранилище
  • Если не удалось показать сообщение об ошибке в консоли для разработчика
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
if(loggedIn) {
    // Fetch current user data
    $.ajax({
        type: ‘POST’,
        url: opt.ajaxUrl,
        data: {
            ‘action’ : ‘fetch_user_data’,
            ‘dataType’: ‘json’
        },
        success:function(data) {
            userData = JSON.parse(data);
            if (typeof(userData[‘wishlist’]) != ‘undefined’ && userData[‘wishlist’] != null && userData[‘wishlist’] != «») {
 
                var userWishlist = userData[‘wishlist’];
                userWishlist = userWishlist.split(‘,’);
 
                if (wishlist.length) {
                    wishlist = wishlist.concat(userWishlist);
 
                    $.ajax({
                        type: ‘POST’,
                        url:opt.ajaxPost,
                        data:{
                            action:’user_wishlist_update’,
                            user_id :userData[‘user_id’],
                            wishlist :wishlist.join(‘,’),
                        }
                    });
 
                } else {
                    wishlist = userWishlist;
                }
 
                wishlist = wishlist.unique();
 
                highlightWishlist(wishlist,inWishlist);
                sessionStorage.removeItem(shopName);
 
            } else {
                if (typeof(ls) != ‘undefined’ && ls != null) {
                    ls = ls.split(‘,’);
                    ls = ls.unique();
                    wishlist = ls;
                }
 
                $.ajax({
                    type: ‘POST’,
                    url:opt.ajaxPost,
                    data:{
                        action:’user_wishlist_update’,
                        user_id :userData[‘user_id’],
                        wishlist :wishlist.join(‘,’),
                    }
                })
                .done(function(response) {
                    highlightWishlist(wishlist,inWishlist);
                    sessionStorage.removeItem(shopName);
                });
            }
        },
        error: function(){
            console.log(‘No user data returned’);
        }
    });
}

Получить список желаний из сеанса / локального хранилища

1
2
3
4
5
6
7
else {
    if (typeof(ls) != ‘undefined’ && ls != null) {
        ls = ls.split(‘,’);
        ls = ls.unique();
        wishlist = ls;
    }
}

Как вы могли заметить, у нас есть двойной AJAX и некоторые вспомогательные функции. Итак, сначала давайте создадим действия запросов AJAX, а затем я объясню наши вспомогательные функции. Я не буду подробно описывать функциональность AJAX в WordPress, но если вы новичок в AJAX и WordPress, я настоятельно рекомендую прочитать это удивительное руководство:

  • Плагины
    Учебник по Ajax в интерфейсе WordPress: понимание процесса
    Том Макфарлин

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

01
02
03
04
05
06
07
08
09
10
11
// Get current user data
function fetch_user_data() {
    if (is_user_logged_in()){
        $current_user = wp_get_current_user();
        $current_user_wishlist = get_user_meta( $current_user->ID, ‘wishlist’,true);
        echo json_encode(array(‘user_id’ => $current_user->ID,’wishlist’ => $current_user_wishlist));
    }
    die();
}
add_action( ‘wp_ajax_fetch_user_data’, ‘fetch_user_data’ );
add_action( ‘wp_ajax_nopriv_fetch_user_data’, ‘fetch_user_data’ );

Наиболее важной частью здесь является имя действия ( fetch_user_data ) — убедитесь, что оно одинаково для AJAX и для функций wp_ajax_fetch_user_data и wp_ajax_nopriv_fetch_user_data . Здесь мы готовим данные в формате JSON с данными идентификатора пользователя и списка пожеланий пользователя.

Наш следующий AJAX-запрос обновляет список пожеланий пользователя, если уже были элементы списка желаний из сеанса / локального хранилища. Присмотритесь к параметру url — увидите, что он другой.

Логика та же, что и для первого действия — разница в том, что здесь мы не возвращаем и не выводим какие-либо данные, но мы обновляем опцию списка желаний для текущего пользователя.

01
02
03
04
05
06
07
08
09
10
11
12
function update_wishlist_ajax(){
    if (isset($_POST[«user_id»]) && !empty($_POST[«user_id»])) {
        $user_id = $_POST[«user_id»];
        $user_obj = get_user_by(‘id’, $user_id);
        if (!is_wp_error($user_obj) && is_object($user_obj)) {
            update_user_meta( $user_id, ‘wishlist’, $_POST[«wishlist»]);
        }
    }
    die();
}
add_action(‘admin_post_nopriv_user_wishlist_update’, ‘update_wishlist_ajax’);
add_action(‘admin_post_user_wishlist_update’, ‘update_wishlist_ajax’);

И если наш пользователь — гость, нам нужно проверить, есть ли какие-либо подробности в списке желаний в сеансе / локальном хранилище.

Прежде чем мы перейдем к части событий, я хочу объяснить наши вспомогательные функции

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Array.prototype.unique = function() {
  return this.filter(function (value, index, self) {
    return self.indexOf(value) === index;
  });
}
 
function isInArray(value, array) {return array.indexOf(value) > -1;}
 
function onWishlistComplete(target, title){
    setTimeout(function(){
        target
        .removeClass(‘loading’)
        .addClass(‘active’)
        .attr(‘title’,title);
    },800);
}
 
function highlightWishlist(wishlist,title){
    $(‘.wishlist-toggle’).each(function(){
        var $this = $(this);
        var currentProduct = $this.data(‘product’);
        currentProduct = currentProduct.toString();
        if (isInArray(currentProduct,wishlist)) {
            $this.addClass(‘active’).attr(‘title’,title);
        }
    });
}

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

Теперь давайте добавим событие click к списку желаний, чтобы включить актуальную функциональность. При каждом событии щелчка переключателя запускается анимация, и если пользователь вошел в систему, действие обновления списка пожеланий запускается с помощью AJAX. Если пользователь является гостем, элемент добавляется в сеансовое / локальное хранилище.

Теперь, если вы перейдете на страницу магазина, обновите браузер и нажмете на любой переключатель списка желаний, вы увидите, что он работает!

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
$(‘.wishlist-toggle’).each(function(){
 
    var $this = $(this);
 
    var currentProduct = $this.data(‘product’);
 
    currentProduct = currentProduct.toString();
 
    if (!loggedIn && isInArray(currentProduct,wishlist)) {
        $this.addClass(‘active’).attr(‘title’,inWishlist);
    }
 
    $(this).on(‘click’,function(e){
        e.preventDefault();
        if (!$this.hasClass(‘active’) && !$this.hasClass(‘loading’)) {
 
            $this.addClass(‘loading’);
 
            wishlist.push(currentProduct);
            wishlist = wishlist.unique();
 
            if (loggedIn) {
                // get user ID
                if (userData[‘user_id’]) {
                    $.ajax({
                        type: ‘POST’,
                        url:opt.ajaxPost,
                        data:{
                            action:’user_wishlist_update’,
                            user_id :userData[‘user_id’],
                            wishlist :wishlist.join(‘,’),
                        }
                    })
                    .done(function(response) {
                        onWishlistComplete($this, inWishlist);
                    })
                    .fail(function(data) {
                        alert(opt.error);
                    });
                }
            } else {
 
                sessionStorage.setItem(shopName, wishlist.toString());
                onWishlistComplete($this, inWishlist);
 
            }
 
        }
 
 
    });
});

Теперь пришло время перечислить наши элементы списка желаний в таблице пожеланий, которую мы создали ранее.

Добавьте следующий код в main.js в самом низу нашей функции-оболочки:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
setTimeout(function(){
 
    if (wishlist.length) {
 
        restUrl += ‘?include=’+wishlist.join(‘,’);
        restUrl += ‘&per_page=’+wishlist.length;
 
        $.ajax({
            dataType: ‘json’,
            url:restUrl
        })
        .done(function(response){
            $(‘.wishlist-table’).each(function(){
                var $this = $(this);
                $.each(response,function(index,object){
                    $this.append(‘<tr data-product=»‘+object.id+’»><td><a class=»wishlist-remove» href=»#» title=»‘+opt.removeWishlist+’»></a>’+object.image+'</td><td>’+object.title[«rendered»]+'</td><td>’+object.price+'</td><td>’+object.stock+'</td><td><a class=»details» href=»‘+object.link+’»>’+opt.buttonText+'</a></td></tr>’);
                });
            });
        })
        .fail(function(response){
            alert(opt.noWishlist);
        })
        .always(function(response){
            $(‘.wishlist-table’).each(function(){
                $(this).removeClass(‘loading’);
            });
        });
 
    } else {
        $(‘.wishlist-table’).each(function(){
            $(this).removeClass(‘loading’);
        });
    }
 
},1000);

Здесь мы используем WordPress REST API для получения продуктов по идентификатору в массиве списков желаний.

Для каждого продукта, который мы получаем, мы добавляем строку таблицы с необходимыми данными для отображения. Нам нужны изображение товара, название, статус товара, кнопка и цена.

Здесь у нас есть два варианта для REST API:

  1. используя WordPress REST API
  2. используя REST API WooCommerce.

Разница в том, что данные о продукте уже присутствуют в REST API Woocommerce, но требуется ключ API. По умолчанию WordPress REST API данные о продукте отсутствуют, но могут быть добавлены, и ключ API не требуется. Для такой простой задачи, как список пожеланий, я не думаю, что нужен ключ API, поэтому мы сделаем это, расширив API WordPress REST по умолчанию, чтобы вернуть цену продукта, код изображения и уровень запасов.

Перейдите в основной файл плагина и в самом низу добавьте следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// Extend REST API
function rest_register_fields(){
 
    register_rest_field(‘product’,
        ‘price’,
        array(
            ‘get_callback’ => ‘rest_price’,
            ‘update_callback’ => null,
            ‘schema’ => null
        )
    );
 
    register_rest_field(‘product’,
        ‘stock’,
        array(
            ‘get_callback’ => ‘rest_stock’,
            ‘update_callback’ => null,
            ‘schema’ => null
        )
    );
 
    register_rest_field(‘product’,
        ‘image’,
        array(
            ‘get_callback’ => ‘rest_img’,
            ‘update_callback’ => null,
            ‘schema’ => null
        )
    );
}
add_action(‘rest_api_init’,’rest_register_fields’);
 
function rest_price($object,$field_name,$request){
 
    global $product;
 
    $id = $product->get_id();
 
    if ($id == $object[‘id’]) {
        return $product->get_price();
    }
 
}
 
function rest_stock($object,$field_name,$request){
 
    global $product;
 
    $id = $product->get_id();
 
    if ($id == $object[‘id’]) {
        return $product->get_stock_status();
    }
 
}
 
function rest_img($object,$field_name,$request){
 
    global $product;
 
    $id = $product->get_id();
 
    if ($id == $object[‘id’]) {
        return $product->get_image();
    }
 
}
 
function maximum_api_filter($query_params) {
    $query_params[‘per_page’][«maximum»]=100;
    return $query_params;
}
add_filter(‘rest_product_collection_params’, ‘maximum_api_filter’);

Все это создает новые поля для REST API и расширяет максимальное количество элементов на запрос. Опять же, если вы новичок в этой теме, я настоятельно рекомендую прочитать эту серию .

А пока, если вы перейдете к таблице желаний и обновите страницу, вы увидите список предметов, которые добавлены в ваш список желаний.

Мы почти закончили; остается только функция удаления. Итак, давайте создадим это! Добавьте следующий код в самом низу функции-оболочки в файле main.js

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
$(document).on(‘click’, ‘.wishlist-remove’, function(){
 
    var $this = $(this);
 
    $this.closest(‘table’).addClass(‘loading’);
 
    wishlist = [];
 
    $this.closest(‘table’).find(‘tr’).each(function(){
 
        if ($(this).data(‘product’) != $this.closest(‘tr’).data(‘product’)) {
 
            wishlist.push($(this).data(‘product’));
 
            if (loggedIn) {
 
                // get user ID
                if (userData[‘user_id’]) {
                    $.ajax({
                        type: ‘POST’,
                        url:opt.ajaxPost,
                        data:{
                            action:’user_wishlist_update’,
                            user_id :userData[‘user_id’],
                            wishlist :wishlist.join(‘,’),
                        }
                    })
                    .done(function(response) {
                        $this.closest(‘table’).removeClass(‘loading’);
                        $this.closest(‘tr’).remove();
                    })
                    .fail(function(data) {
                        alert(opt.error);
                    });
                }
            } else {
                sessionStorage.setItem(shopName, wishlist.toString());
                setTimeout(function(){
                    $this.closest(‘table’).removeClass(‘loading’);
                    $this.closest(‘tr’).remove();
                },500);
            }
        }
 
    });
 
});

Когда щелкнет значок удаления (убедитесь, что у вас есть remove.svg в папке с изображениями , вы можете использовать любой значок, какой захотите), нам нужно проверить, вошел ли пользователь в систему. Если это так, мы удаляем идентификатор элемента из user_wishlist_update желаний, используя AJAX с user_wishlist_update
действие. Если пользователь — гость, нам нужно удалить идентификатор элемента из сеанса / локального хранилища.

Теперь перейдите к вашему списку пожеланий и обновите страницу. Как только вы нажмете на значок удаления, ваш элемент будет удален из списка желаний.

Это был настоящий проект! Простая, но всеобъемлющая функция списка желаний для ваших магазинов WooCommerce. Вы можете использовать этот плагин в любом проекте; Вы можете расширять, изменять его и вносить предложения. Надеюсь, тебе понравилось. Вот ссылка на исходные файлы на GitHub . И вот демо .

В Tuts + у нас есть большая коллекция учебных пособий и курсов для изучения WooCommerce. Проверьте эти четыре отличных курса, чтобы начать!

  • WooCommerce
    И работает с WooCommerce
    Рэйчел Макколлин
  • WordPress
    Разработка темы WooCommerce
    Рэйчел Макколлин
  • WordPress
    Идти дальше с темами WooCommerce
    Рэйчел Макколлин
  • WordPress
    Как сделать вашу тему WooCommerce совместимой
    Рэйчел Макколлин