1. Web Design
  2. eCommerce
  3. WooCommerce

So erstellen Sie ein AJAX-basiertes Live-Produktsuch-Widget für WooCommerce

Scroll to top

German (Deutsch) translation by Władysław Łucyszyn (you can also view the original English article)

AJAX (Asynchronous Javascript and XML) ist eine Möglichkeit, eine Webseite mit einem Server zu kommunizieren und ihren Inhalt zu aktualisieren, ohne die Seite neu zu laden. Mit WooCommerce können wir mit AJAX Produkte direkt in den Warenkorb legen, Produkte im laufenden Betrieb anpassen, Produktlisten filtern und vieles mehr.

In diesem Tutorial erstellen wir ein Produkt-Plugin für die "live search" mit einem Produktkategoriefilter und einer Keyword-Eingabe. Alles natürlich mit AJAX.

Unser Plugin gibt uns ein benutzerdefiniertes Widget, das dann überall im WooCommerce Store platziert werden kann. Es sieht folgendermaßen aus (die Ästhetik ändert sich je nach verwendetem WordPress-Thema):

ajax product searchajax product searchajax product search

1. Erstellen Sie den Plugin-Ordner

Beginnen Sie mit der Erstellung eines Ordners namens "Produktsuche" und der darin enthaltenen PHP-Hauptdatei "product-search.php". Öffnen Sie die Datei und fügen Sie den folgenden Header-Kommentar hinzu, wobei Sie die relevanten Details in Ihre eigenen ändern:

1
/*

2
    Plugin Name: Woocommerce AJAX product search

3
    Plugin URI: https://www.enovathemes.com

4
    Description: Ajax product search for WooCommerce

5
    Author: Enovathemes

6
    Version: 1.0

7
    Author URI: https://enovathemes.com

8
*/
9
10
if ( ! defined( 'ABSPATH' ) ) {
11
    exit; // Exit if accessed directly

12
}

Hier beschreiben wir, was unser Plugin ist und was es tut. Ich werde die Plugin-Entwicklung nicht im Detail behandeln, da dies den Rahmen dieses Tutorials sprengt. Wenn Sie jedoch noch nicht mit der Plugin-Entwicklung vertraut sind, empfehle ich dringend, einen Blick auf diesen Anfängerkurs zu werfen:

  • WordPress
    Einführung in die Entwicklung von WordPress-Plugins
    Rachel McCollin

2. Planen Sie unsere Plugin-Entwicklung

Hier ist unser Plan: Wir haben eine Sucheingabe mit einem ausgewählten Element, um die Produktkategorie zu definieren. All dies wird in ein Widget gepackt. Benutzer können nach einem Schlüsselwort innerhalb einer bestimmten Produktkategorie suchen.

Immer wenn der Benutzer ein Produktschlüsselwort oder eine Produkt-SKU eingibt, werden wir eine AJAX-Anfrage stellen, um Produkte abzufragen, die der Kategorie entsprechen (falls definiert) und das angegebene Schlüsselwort im Titel, Inhalt oder der angegebenen SKU enthalten. Dem Benutzer wird eine Liste mit Suchergebnissen angezeigt.

Unser nächster Schritt besteht darin, den Plugin-Stil und die Skriptdateien in die Warteschlange zu stellen.

3. Plugin-Dateien in die Warteschlange stellen

Fügen Sie nach dem Plugin-Intro den folgenden Code hinzu:

1
function search_plugin_scripts_styles(){
2
    if (class_exists("Woocommerce")) {
3
4
        wp_enqueue_style( 'search-style', plugins_url('/css/style.css', __FILE__ ), array(), '1.0.0' );
5
        wp_register_script( 'search-main', plugins_url('/js/main.js', __FILE__ ), array('jquery'), '', true);
6
        wp_localize_script(
7
            'search-main',
8
            'opt',
9
            array(
10
                'ajaxUrl'   => admin_url('admin-ajax.php'),
11
                'noResults' => esc_html__( 'No products found', 'textdomain' ),
12
            )
13
        );
14
    }
15
}
16
add_action( 'wp_enqueue_scripts', 'search_plugin_scripts_styles' );

Stellen Sie sicher, dass Sie entsprechende Ordner für Stile und Skripte (CSS- und JS-Ordner) und die entsprechenden Dateien (style.css und main.js) erstellen.

Für die Datei main.js müssen einige Parameter mit der Funktion wp_localize_script übergeben werden. Diese Parameter geben uns die AJAX-URL und den Text "no results", sodass wir sie nicht fest in unser Skript codieren müssen.

4. Holen Sie sich die Taxonomie der Produktkategorie mit Hierarchie

Als nächstes müssen wir alle Produktkategorien mit Hierarchie sammeln und zwischenspeichern. Dies wird für die Optionen zur Kategorieauswahl verwendet.

Diese Aufgabe besteht aus 4 Schritten:

  1. Holen Sie sich Produktkategorie Taxonomie mit Hierarchie
  2. Listen Sie die Taxonomie der Produktkategorien mit der Hierarchie als Auswahloptionen auf
  3. Zwischenspeichern Sie die Ergebnisse der Produktkategorie-Taxonomie
  4. Löschen Sie vorübergehende Produktkategorien (Cache) beim Bearbeiten von Begriffen und beim Speichern nach dem Speichern

Holen Sie sich Taxonomie

Hier habe ich eine rekursive Funktion erstellt, die die angegebenen Taxonomiebegriffe mit der Eltern-Kind-Beziehung sammelt:

1
function get_taxonomy_hierarchy( $taxonomy, $parent = 0, $exclude = 0) {
2
    $taxonomy = is_array( $taxonomy ) ? array_shift( $taxonomy ) : $taxonomy;
3
    $terms = get_terms( $taxonomy, array( 'parent' => $parent, 'hide_empty' => false, 'exclude' => $exclude) );
4
5
    $children = array();
6
    foreach ( $terms as $term ){
7
        $term->children = get_taxonomy_hierarchy( $taxonomy, $term->term_id, $exclude);
8
        $children[ $term->term_id ] = $term;
9
    }
10
    return $children;
11
}

Produktkategorien als Auswahloptionen auflisten

Als nächstes müssen wir die gesammelten Begriffe mit einer anderen rekursiven Funktion auflisten. Es erstellt die auf option und optgroup basierende HTML-Struktur:

1
function list_taxonomy_hierarchy_no_instance( $taxonomies) {
2
?>
3
    <?php foreach ( $taxonomies as $taxonomy ) { ?>
4
        <?php $children = $taxonomy->children; ?>
5
        <option value="<?php echo $taxonomy->term_id; ?>"><?php echo $taxonomy->name; ?></option>
6
        <?php if (is_array($children) && !empty($children)): ?>
7
            <optgroup>
8
                <?php list_taxonomy_hierarchy_no_instance($children); ?>
9
            </optgroup>
10
        <?php endif ?>
11
    <?php } ?>
12
13
<?php
14
}

Zwischenspeichern der Ergebnisse der Produktkategorie

Abgefragte Ergebnisse müssen zwischengespeichert werden, um den Filterrenderprozess nicht zu verlangsamen. Hier müssen wir also einen Übergang für Produktkategorien erstellen. Ich werde die Transients-API nicht im Detail beschreiben, aber wenn Sie mit dem Thema noch nicht vertraut sind, empfehle ich dringend, diese erstaunlichen Einführungs-Tutorials zu lesen:

  • Themenentwicklung
    Erste Schritte mit der WordPress Transients API, Teil 1
    Tom McFarlin
  • Plugins
    Erste Schritte mit der WordPress Transient API, Teil 2
    Tom McFarlin

Im Moment ist hier die Produktkategorie vorübergehend:

1
function get_product_categories_hierarchy() {
2
3
    if ( false === ( $categories = get_transient( 'product-categories-hierarchy' ) ) ) {
4
5
        $categories = get_taxonomy_hierarchy( 'product_cat', 0, 0);
6
7
        // do not set an empty transient - should help catch private or empty accounts.

8
        if ( ! empty( $categories ) ) {
9
            $categories = base64_encode( serialize( $categories ) );
10
            set_transient( 'product-categories-hierarchy', $categories, apply_filters( 'null_categories_cache_time', 0 ) );
11
        }
12
    }
13
14
    if ( ! empty( $categories ) ) {
15
16
        return unserialize( base64_decode( $categories ) );
17
18
    } else {
19
20
        return new WP_Error( 'no_categories', esc_html__( 'No categories.', 'textdomain' ) );
21
22
    }
23
}

Löschen Sie vorübergehende Produktkategorien (Cache) beim Bearbeiten von Begriffen und beim Speichern nach dem Speichern

Schließlich müssen wir den Übergang löschen, wenn ein Benutzer eine Produktkategorie aktualisiert oder erstellt oder das Produkt selbst aktualisiert / erstellt.

1
function edit_product_term($term_id, $tt_id, $taxonomy) {
2
    $term = get_term($term_id,$taxonomy);
3
    if (!is_wp_error($term) && is_object($term)) {
4
        $taxonomy = $term->taxonomy;
5
        if ($taxonomy == "product_cat") {
6
            delete_transient( 'product-categories-hierarchy' );
7
        }
8
    }
9
}
10
11
function delete_product_term($term_id, $tt_id, $taxonomy, $deleted_term) {
12
    if (!is_wp_error($deleted_term) && is_object($deleted_term)) {
13
        $taxonomy = $deleted_term->taxonomy;
14
        if ($taxonomy == "product_cat") {
15
            delete_transient( 'product-categories-hierarchy' );
16
        }
17
    }
18
}
19
add_action( 'create_term', 'edit_product_term', 99, 3 );
20
add_action( 'edit_term', 'edit_product_term', 99, 3 );
21
add_action( 'delete_term', 'delete_product_term', 99, 4 );
22
23
add_action( 'save_post', 'save_post_action', 99, 3);
24
function save_post_action( $post_id ){
25
26
    if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
27
    if (!current_user_can( 'edit_page', $post_id ) ) return;
28
29
    $post_info = get_post($post_id);
30
31
    if (!is_wp_error($post_info) && is_object($post_info)) {
32
        $content   = $post_info->post_content;
33
        $post_type = $post_info->post_type;
34
35
        if ($post_type == "product"){
36
            delete_transient( 'enovathemes-product-categories' );
37
        }
38
    }
39
40
}

Wir werden Aktionen für create_term, edit_term, delete_term und save_post hinzufügen

5. Erstellen Sie das Widget

Jetzt ist es Zeit, das Widget selbst zu erstellen. Ich werde den Widget-Erstellungsprozess nicht im Detail beschreiben, aber wenn Sie sich auf dem Laufenden halten müssen, empfehle ich dieses Tutorial:

  • WordPress
    Einführung in das Erstellen Ihres ersten WordPress-Widgets
    Rachel McCollin

Fügen Sie vorerst den folgenden Code hinzu, um das Widget zu erstellen:

1
add_action('widgets_init', 'register_product_search_widget');
2
function register_product_search_widget(){
3
    register_widget( 'Enovathemes_Addons_WP_Product_Search' );
4
}
5
6
class Enovathemes_Addons_WP_Product_Search extends WP_Widget {
7
8
        public function __construct() {
9
                parent::__construct(
10
                        'product_search_widget',
11
                        esc_html__('* Product ajax search', 'textdomain'),
12
                        array( 'description' => esc_html__('Product ajax search', 'textdomain'))
13
                );
14
        }
15
16
        public function widget( $args, $instance) {
17
18
                wp_enqueue_script('search-main');
19
20
                extract($args);
21
22
                $title = apply_filters( 'widget_title', $instance['title'] );
23
24
                echo $before_widget;
25
26
                        if ( ! empty( $title ) ){echo $before_title . $title . $after_title;}
27
28
            ?>
29
30
                        <div class="product-search">
31
                                <form name="product-search" method="POST">
32
                    <?php $categories = get_product_categories_hierarchy(); ?>
33
                    <?php if ($categories): ?>
34
                        <select name="category" class="category">
35
                            <option class="default" value=""><?php echo esc_html__( 'Select a category', 'textdomain' ); ?></option>
36
                            <?php list_taxonomy_hierarchy_no_instance( $categories); ?>
37
                        </select>
38
                    <?php endif ?>
39
                    <div class="search-wrapper">
40
                        <input type="search" name="search" class="search" placeholder="<?php echo esc_html__( 'Search for product...', 'textdomain' ); ?>" value="">
41
                        <?php echo file_get_contents(plugins_url( 'images/loading.svg', __FILE__ )); ?>
42
                    </div>
43
                    </form>
44
                <div class="search-results"></div>
45
                </div>
46
47
                <?php echo $after_widget;
48
        }
49
50
        public function form( $instance ) {
51
52
                $defaults = array(
53
                        'title' => esc_html__('Product search', 'textdomain'),
54
                );
55
56
                $instance = wp_parse_args((array) $instance, $defaults);
57
58
                ?>
59
60
                <div id="<?php echo esc_attr($this->get_field_id( 'widget_id' )); ?>">
61
62
                        <p>
63
                                <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php echo esc_html__( 'Title:', 'textdomain' ); ?></label>
64
                                <input class="widefat <?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $instance['title'] ); ?>" />
65
                        </p>
66
67
                </div>
68
69
                <?php
70
        }
71
72
        public function update( $new_instance, $old_instance ) {
73
                $instance = $old_instance;
74
                $instance['title'] = strip_tags( $new_instance['title'] );
75
                return $instance;
76
        }
77
78
}

Unser Widget hat keine Optionen, aber Sie können einen Titel eingeben. Es ist ein einfaches Formular mit einem Suchfeld und einer Kategorieauswahl. Und für die Kategorieauswahl verwenden wir die zuvor erstellte Funktion:

get_product_categories_hierarchy und list_taxonomy_hierarchy_no_instance. Außerdem benötigen wir eine SVG-Datei, um das Laden bei der AJAX-Abfrage zu kennzeichnen.

Wenn Sie zunächst zu Darstellung > Widgets gehen, wird ein neues Widget angezeigt, sodass Sie es dem Widget-Bereich hinzufügen und im Front-End Folgendes sehen können:

search widget search widget search widget

Sieht schrecklich aus! Fügen wir einige Stile hinzu.

6. Fügen Sie einige Stile hinzu

Öffnen Sie die Datei style.css und fügen Sie Folgendes hinzu:

1
.product-search {
2
    position: relative;
3
    padding: 24px;
4
    border-radius: 4px;
5
    box-shadow:0px 0px 24px 0px rgba(0, 0, 0, 0.08);
6
    border:1px solid #e0e0e0;
7
    background: #f5f5f5;
8
}
9
10
.search-results {
11
    display: none;
12
    position: absolute;
13
    width: 200%;
14
    background: #ffffff;
15
    padding:12px 24px;
16
    border: 1px solid #e0e0e0;
17
    z-index: 15;
18
    transform: translateY(-1px);
19
}
20
21
.search-results.active {
22
    display: block;
23
}
24
25
.search-results ul {
26
    list-style: none;
27
    margin:0 !important;
28
    padding: 0 !important;
29
}
30
31
.search-results ul li {
32
    display: block;
33
    padding: 12px 0;
34
    position: relative;
35
    border-bottom: 1px dashed #e0e0e0;
36
}
37
38
.search-results ul li:last-child {
39
    border-bottom: none;
40
}
41
42
.search-results ul li a {
43
    display: table;
44
    width: 100%;
45
}
46
47
.search-results ul li a > * {
48
    display: table-cell;
49
    vertical-align: top;
50
}
51
52
.search-results .product-image {
53
    width: 72px;
54
    max-width: 72px;
55
}
56
57
.product-data {
58
    padding-left: 24px;
59
}
60
61
.search-results h3 {
62
    display: block;
63
}
64
65
.product-data div:not(.product-categories) {
66
    display: inline-block;
67
    vertical-align: middle;
68
}
69
70
.product-data .product-price {
71
    position: absolute;
72
    top: 12px;
73
    right: 0;
74
}
75
76
.product-data .product-stock {
77
    padding: 4px 8px;
78
    background: #eeeeee;
79
    border-radius: 4px;
80
    position: absolute;
81
    bottom: 12px;
82
    right: 0;
83
}
84
85
.product-categories > span {
86
    display: inline-block;
87
    margin-right: 4px;
88
}
89
90
.product-categories > span:after {
91
    content: ",";
92
}
93
94
.product-categories > span:last-child:after {
95
    content: "";
96
}
97
98
.product-categories > span:last-child {
99
    margin-right:0;
100
}
101
102
.product-search select {
103
    width: 100% !important;
104
    min-height: 40px !important;
105
    margin-bottom: 16px;
106
}
107
108
.product-search select,
109
.product-search input {
110
    background: #ffffff;
111
    border:1px solid #e0e0e0;
112
}
113
114
.search-wrapper {
115
    position: relative;
116
}
117
118
.search-wrapper input {
119
    padding-right: 35px !important;
120
}
121
122
.search-wrapper svg {
123
    position: absolute;
124
    top: 10px;
125
    right: 10px;
126
    width: 20px;
127
    height: 20px;
128
    fill:#bdbdbd;
129
    animation:loading 500ms 0ms infinite normal linear;
130
    transform-origin: center;
131
    opacity: 0;
132
}
133
134
.search-wrapper.loading svg {
135
    opacity:1;
136
}
137
138
@keyframes loading {
139
    from {transform: rotate(0deg);}
140
    to {transform: rotate(360deg);}
141
}

Aktualisieren Sie nun den Browser (vergessen Sie nicht den Browser-Cache) und Ihr Widget sollte viel besser aussehen:

product searchproduct searchproduct search

Im Moment macht es überhaupt nichts, also wenden wir einige Funktionen an.

7. Suchfunktionen hinzufügen

Öffnen Sie die Datei main.js. Hier erstellen wir unsere Kernsuchfunktion.

Die Idee ist einfach: Wir werden Ereignis-Listener hinzufügen, um die Eingabe-Eingabe (Eingabe) zu suchen und die Feldänderung auszuwählen. Immer wenn eines dieser Ereignisse ausgelöst wird, werden wir eine AJAX-Anfrage stellen, um das Schlüsselwort zu senden, Produkte basierend auf dem Schlüsselwort abzufragen und die angegebenen Ergebnisse auszugeben.

Fügen Sie der Datei main.js den folgenden Code hinzu:

1
(function($){
2
3
    "use strict";
4
$('form[name="product-search"]').each(function(){
5
6
        var form          = $(this),
7
            search        = form.find('.search'),
8
            category      = form.find('.category'),
9
            currentQuery  = '',
10
            timeout       = false;
11
12
        category.on('change',function(){
13
            currentQuery  = '';
14
            var query = search.val();
15
            productSearch(form,query,currentQuery,timeout);
16
        });
17
18
        search.keyup(function(){
19
            var query = $(this).val();
20
            productSearch(form,query,currentQuery,timeout);
21
        });
22
23
    });
24
25
})(jQuery);

Hier haben wir einige erforderliche Variablen definiert und der ausgewählten Suche Ereignis-Listener hinzugefügt. Wie Sie sehen können, lösen beide Ereignisse dieselbe Funktion productSearch aus, die mehrere Parameter hat:

  • form
  • query
  • currentQuery
  • timeout;

productSearch-Funktion

Wir haben diese Funktion noch nicht, daher funktioniert die Suche vorerst nicht. Erstellen wir also diese Funktion. Fügen Sie den folgenden Code direkt vor dem vorherigen hinzu.

1
function productSearch(form,query,currentQuery,timeout){
2
3
    var search   = form.find('.search'),
4
        category = form.find('.category');
5
6
    form.next('.search-results').html('').removeClass('active');
7
8
    query = query.trim();
9
10
    if (query.length >= 3) {
11
12
        if (timeout) {
13
            clearTimeout(timeout);
14
        }
15
16
        form.next('.search-results').removeClass('empty');
17
18
        search.parent().addClass('loading');
19
        if (query != currentQuery) {
20
            timeout = setTimeout(function() {
21
22
                $.ajax({
23
                    url:opt.ajaxUrl,
24
                    type: 'post',
25
                    data: { action: 'search_product', keyword: query, category: category.val() },
26
                    success: function(data) {
27
                        currentQuery = query;
28
                        search.parent().removeClass('loading');
29
30
                        if (!form.next('.search-results').hasClass('empty')) {
31
32
                            if (data.length) {
33
                                form.next('.search-results').html('<ul>'+data+'</ul>').addClass('active');
34
                            } else {
35
                                form.next('.search-results').html(opt.noResults).addClass('active');
36
                            }
37
38
                        }
39
40
                        clearTimeout(timeout);
41
                        timeout = false;
42
43
44
                    }
45
                });
46
47
            }, 500);
48
        }
49
    } else {
50
51
        search.parent().removeClass('loading');
52
        form.next('.search-results').empty().removeClass('active').addClass('empty');
53
54
        clearTimeout(timeout);
55
        timeout = false;
56
57
    }
58
}

In dieser Funktion stellen wir zunächst sicher, dass unser Keyword mindestens 3 Zeichen enthält und keine Leerzeichen enthält

Wenn unsere Keyword-Länge mehr oder weniger 3 Zeichen beträgt, fügen wir die Ladeklasse dem übergeordneten Suchfeld-Wrapper hinzu. Dies ist erforderlich, um die CSS-Animation auszuführen, während wir unsere AJAX-Anforderung stellen.

Und hier müssen wir überprüfen, ob das eingegebene Keyword nicht dem aktuellen Keyword entspricht, um doppelte AJAX-Anforderungen für dasselbe Keyword zu vermeiden. Als nächstes setzen wir das Timeout auf 500 ms und stellen eine AJAX-Anfrage. Mit der Anfrage übergeben wir das Schlüsselwort, die Kategorie und die AJAX-Anforderungsaktion search_product.

Da wir noch keine search_product-Aktion haben, wird beim Erstellen des AJAX ein interner Serverfehler angezeigt. Lassen Sie uns nun diese Aktion erstellen.

search_product Aktion

Öffnen Sie die Hauptdatei product-search.php und fügen Sie ganz unten den folgenden Code hinzu:

1
function search_product() {
2
3
    global $wpdb, $woocommerce;
4
5
    if (isset($_POST['keyword']) && !empty($_POST['keyword'])) {
6
7
        $keyword = $_POST['keyword'];
8
9
        if (isset($_POST['category']) && !empty($_POST['category'])) {
10
11
            $category = $_POST['category'];
12
13
            $querystr = "SELECT DISTINCT * FROM $wpdb->posts AS p

14
            LEFT JOIN $wpdb->term_relationships AS r ON (p.ID = r.object_id)

15
            INNER JOIN $wpdb->term_taxonomy AS x ON (r.term_taxonomy_id = x.term_taxonomy_id)

16
                INNER JOIN $wpdb->terms AS t ON (r.term_taxonomy_id = t.term_id)

17
                WHERE p.post_type IN ('product')

18
                AND p.post_status = 'publish'

19
            AND x.taxonomy = 'product_cat'

20
                AND (

21
                (x.term_id = {$category})

22
                OR

23
                (x.parent = {$category})

24
            )

25
            AND (

26
                (p.ID IN (SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_sku' AND meta_value LIKE '%{$keyword}%'))

27
                OR

28
                (p.post_content LIKE '%{$keyword}%')

29
                OR

30
                (p.post_title LIKE '%{$keyword}%')

31
            )

32
                ORDER BY t.name ASC, p.post_date DESC;";
33
34
        } else {
35
            $querystr = "SELECT DISTINCT $wpdb->posts.*

36
            FROM $wpdb->posts, $wpdb->postmeta

37
            WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id

38
            AND (

39
                ($wpdb->postmeta.meta_key = '_sku' AND $wpdb->postmeta.meta_value LIKE '%{$keyword}%')

40
                OR

41
                ($wpdb->posts.post_content LIKE '%{$keyword}%')

42
                OR

43
                ($wpdb->posts.post_title LIKE '%{$keyword}%')

44
            )

45
            AND $wpdb->posts.post_status = 'publish'

46
            AND $wpdb->posts.post_type = 'product'

47
            ORDER BY $wpdb->posts.post_date DESC";
48
        }
49
50
        $query_results = $wpdb->get_results($querystr);
51
52
        if (!empty($query_results)) {
53
54
            $output = '';
55
56
            foreach ($query_results as $result) {
57
58
                $price      = get_post_meta($result->ID,'_regular_price');
59
                $price_sale = get_post_meta($result->ID,'_sale_price');
60
                $currency   = get_woocommerce_currency_symbol();
61
62
                $sku   = get_post_meta($result->ID,'_sku');
63
                $stock = get_post_meta($result->ID,'_stock_status');
64
65
                $categories = wp_get_post_terms($result->ID, 'product_cat');
66
67
                $output .= '<li>';
68
                    $output .= '<a href="'.get_post_permalink($result->ID).'">';
69
                        $output .= '<div class="product-image">';
70
                            $output .= '<img src="'.esc_url(get_the_post_thumbnail_url($result->ID,'thumbnail')).'">';
71
                        $output .= '</div>';
72
                        $output .= '<div class="product-data">';
73
                            $output .= '<h3>'.$result->post_title.'</h3>';
74
                            if (!empty($price)) {
75
                                $output .= '<div class="product-price">';
76
                                    $output .= '<span class="regular-price">'.$price[0].'</span>';
77
                                    if (!empty($price_sale)) {
78
                                        $output .= '<span class="sale-price">'.$price_sale[0].'</span>';
79
                                    }
80
                                    $output .= $currency;
81
                                $output .= '</div>';
82
                            }
83
                            if (!empty($categories)) {
84
                                $output .= '<div class="product-categories">';
85
                                    foreach ($categories as $category) {
86
                                        if ($category->parent) {
87
                                            $parent = get_term_by('id',$category->parent,'product_cat');
88
                                            $output .= '<span>'.$parent->name.'</span>';
89
                                        }
90
                                        $output .= '<span>'.$category->name.'</span>';
91
                                    }
92
                                $output .= '</div>';
93
                            }
94
                            if (!empty($sku)) {
95
                                $output .= '<div class="product-sku">'.esc_html__( 'SKU:', 'textdomain' ).' '.$sku[0].'</div>';
96
                            }
97
98
                            if (!empty($stock)) {
99
                                $output .= '<div class="product-stock">'.$stock[0].'</div>';
100
                            }
101
102
                        $output .= '</div>';
103
                        $output .= '</a>';
104
                $output .= '</li>';
105
            }
106
107
            if (!empty($output)) {
108
                echo $output;
109
            }
110
        }
111
    }
112
113
    die();
114
}
115
add_action( 'wp_ajax_search_product', 'search_product' );
116
add_action( 'wp_ajax_nopriv_search_product', 'search_product' );

Achten Sie vorerst auf den Teil add_action des Codes. Sehen Sie die Aktionsnamen mit den Präfixen wp_ajax_ und wp_ajax_nopriv_? Wir müssen dieselben Aktionsnamen verwenden, die wir in der Datei main.js angegeben haben - search_product.

Nun zum Aktionskern

Hier verwenden wir die Abfragemethode $wpdb, um den Abfrageprozess zu beschleunigen. Ich bin kein MySQL-Guru, daher können die Profis es meiner Meinung nach optimieren, aber für unsere Aufgabe ist es gut genug und funktioniert wie erwartet.

Hier prüfen wir zuerst, ob eine Kategorie angegeben wurde, und fragen dann die Ergebnisse unter dieser bestimmten Kategorie ab. Wenn keine Kategorie angegeben ist, führen wir eine regelmäßige Produktabfrage durch, die das Schlüsselwort im Titel oder den Inhalt enthält oder mit der SKU übereinstimmt. Und wenn wir die Ergebnisse haben, erstellen wir die Ausgabe basierend auf den abgefragten Ergebnissen.

Nun zurück zu main.js. Wenn unsere AJAX-Anfrage erfolgreich ist, geben wir die Ausgabedaten in der Liste zurück und hängen sie an das leere div der Suchergebnisse an. Alles was bleibt ist, das Timeout zu löschen.

searching logo itemssearching logo itemssearching logo items

Das ist es! Eine effektive und leistungsstarke Produkt-AJAX-Suche. Wenn Sie jetzt zum Front-End gehen, laden Sie die Seite neu (vergessen Sie nicht das Browser-Caching). Sie können nach Produkten suchen und das Widget in Aktion sehen.

Abschluss

Sie können dieses Plugin in Ihren kommerziellen und nichtkommerziellen Projekten verwenden. Ich hoffe es gefällt dir und wenn du irgendwelche Ideen hast, können Sie sie gerne in den Kommentaren schreiben. Sie können das Plugin von GitHub herunterladen. Und hier ist die Plugin-Demo. Danke fürs Lesen!