Slow Loading Attribute Select – WooCommerce Backend

Having a look around in the woocommerce code, there is no ajax request made for this select, so there is no use in caching.
The slowliness comes from javascript/select2 having so many options to display.

Woocommerce, however, left enough actions, filters and hooks so that the behavior of this select2 can be changed

I made a small plugin that will fix your issue by doing an ajax search limited to a 100 terms rather than displaying all of the terms in the select2

functions.php

<?php
/**
 * Plugin name: WC Fix Attributes
 * Version: 1.0
 * Author: Tofandel
 * Description: Fixes the slowliness of a select2 in woocommerce admin when having huge numbers of product variation terms
 */

/**
 * Filter to prevent displaying all of the attribute terms and only display the ones selected in the product
 */
add_filter( 'woocommerce_product_attribute_terms', function ( $args ) {
    global $post;

    if ( $post ) {
        $product = new WC_Product($post);

        $includes = [];
        $size = 0;

        foreach ($product->get_attributes() as $attribute) {
            /**
             * @var WC_Product_Attribute $attribute
             */
            $opts = $attribute->get_options();
            $includes = array_merge($includes, $opts);
            $size = max($size, sizeof($includes));

        }
        $args['include'] = $includes;

        $args['number'] = $size; //Will output only the selected terms
    }
    return $args;
} );

/**
 * Hack so we can get the term taxonomy (because WC forgot to print it somewhere)
 */
add_action( 'woocommerce_product_option_terms', function ( $attribute_taxonomy, $i, $attribute ) {
    echo '<span class="attribute_taxonomy_getter" data-taxonomy="' . esc_attr( $attribute->get_taxonomy() ) . '"></span>';
}, 10, 3 );

/**
 * Enqueue script
 */
add_action( 'admin_enqueue_scripts', function () {
    wp_enqueue_script( 'wc-fix-attributes', plugins_url( 'script.js', __FILE__ ) );

    wp_localize_script( 'wc-fix-attributes', 'WCFixAttributes', [
        'ajaxurl' => admin_url( 'admin-ajax.php' ),
        'nonce' => wp_create_nonce( 'wc_fix_search_terms' ),
    ] );
} );

/**
 * Ajax search
 */
add_action( 'wp_ajax_wc_fix_search_terms', function () {
    // Permissions check.
    check_ajax_referer( 'wc_fix_search_terms' );

    if ( ! current_user_can( 'manage_product_terms' ) ) {
        wp_send_json_error( __( 'You do not have permission to read product attribute terms', 'woocommerce' ) );
    }


    if ( ! empty( $_REQUEST['taxonomy'] ) ) {
        $terms = get_terms( [ 'taxonomy' => $_REQUEST['taxonomy'], 'number' => 100, 'name__like' => $_REQUEST['term'] ] );

        $terms = array_map( function ( $term ) {
            return [ 'text' => $term->name, 'slug' => $term->slug, 'id' => $term->term_id ];
        }, $terms );

        wp_send_json( [ 'results' => $terms, 'success' => true ] );
    } else {
        wp_send_json_error();
    }
} );

script.js

jQuery(function ($) {
    // The woocommerce select2 is initializing
    $(document.body).on('wc-enhanced-select-init', function () {
        //We need to wait a bit for it to be fully inited
        setTimeout(function() {
            $('select.attribute_values').each(function () {
                var $that = $(this);
                $that.select2({ //Add an ajax option to it, to search the terms dynamically
                    ajax: {
                        url: WCFixAttributes.ajaxurl,
                        dataType: 'json',
                        type: "GET",
                        quietMillis: 400, //Typing delay before sending the request
                        data: function (term) {
                            return {
                                action: 'wc_fix_search_terms',
                                _wpnonce: WCFixAttributes.nonce,
                                // Get the taxonomy printed from our action
                                taxonomy: $that.parent().children('.attribute_taxonomy_getter').data('taxonomy'),
                                term: term.term
                            };
                        },
                    }
                });
            });
        }, 100);
    })
});

Just create a directory in your plugins directory (name it however you like) and add those two files or download the zip and upload it in wordpress as you would any plugin

Leave a Comment