Товары апсейл в произвольном порядке

Столкнулся с простой казалось бы проблемой. Хочу управлять порядком в товарах апсейл без дополнительных плагинов и функционалом WooCommerce.

Итак, вы хотите, чтобы порядок апсейл товаров сохранялся в том порядке, в котором вы их выбираете при настройке продукта. Вот решение:

Вставьте этот код в файл function.php дочерней темы WordPress

<?php
//Сохраняем порядок выбранных апселл продуктов
function preserve_upsell_selection_order($post_id) {
    // Проверяем наличие upsell_ids в POST запросе
    if (!isset($_POST['upsell_ids'])) {
        return;
    }

    // Получаем массив ID апселл продуктов в порядке выбора
    $upsell_ids = isset($_POST['upsell_ids']) ? array_map('intval', explode(',', $_POST['upsell_ids'])) : array();
    
    // Фильтруем пустые значения
    $upsell_ids = array_filter($upsell_ids);
    
    // Сохраняем порядок в мета-поле продукта
    update_post_meta($post_id, '_upsell_display_order', $upsell_ids);
}
add_action('woocommerce_process_product_meta', 'preserve_upsell_selection_order', 20);

//Изменяем порядок отображения апселл продуктов
function custom_upsell_display_order($ids, $product_id = null) {
    if (empty($ids)) {
        return $ids;
    }

    // Если product_id не передан, пытаемся получить его из глобального объекта
    if (!$product_id) {
        global $product;
        $product_id = $product ? $product->get_id() : 0;
    }

    // Получаем сохраненный порядок
    $saved_order = get_post_meta($product_id, '_upsell_display_order', true);
    
    if (!empty($saved_order) && is_array($saved_order)) {
        // Сортируем массив ID в соответствии с сохраненным порядком
        $sorted_ids = array();
        foreach ($saved_order as $ordered_id) {
            if (in_array($ordered_id, $ids)) {
                $sorted_ids[] = $ordered_id;
            }
        }
        
        // Добавляем продукты, которые есть в $ids, но отсутствуют в сохраненном порядке
        foreach ($ids as $id) {
            if (!in_array($id, $sorted_ids)) {
                $sorted_ids[] = $id;
            }
        }
        
        return $sorted_ids;
    }

    return $ids;
}
add_filter('woocommerce_product_get_upsell_ids', 'custom_upsell_display_order', 10, 2);
add_filter('woocommerce_product_upsell_ids', 'custom_upsell_display_order', 10, 2);

/**
 * Добавляем JavaScript для сохранения порядка выбора
 */
function add_upsell_order_script() {
    if (get_post_type() !== 'product') {
        return;
    }
    ?>
    <script type="text/javascript">
    jQuery(document).ready(function($) {
        // Находим контейнер с выбранными апселл продуктами
        var $upsellsContainer = $('#upsell_product_data');
        
        // Функция обновления скрытого поля с порядком
        function updateUpsellOrder() {
            var selectedIds = [];
            $upsellsContainer.find('.wc-product-search').each(function() {
                var value = $(this).val();
                if (value) {
                    // Если значение - массив, добавляем все элементы
                    if (Array.isArray(value)) {
                        selectedIds = selectedIds.concat(value);
                    } else {
                        selectedIds.push(value);
                    }
                }
            });
            
            // Обновляем или создаем скрытое поле
            var $hiddenInput = $('#upsell_ids');
            if ($hiddenInput.length === 0) {
                $hiddenInput = $('<input type="hidden" name="upsell_ids" id="upsell_ids" />');
                $upsellsContainer.append($hiddenInput);
            }
            $hiddenInput.val(selectedIds.join(','));
        }

        // Отслеживаем изменения в выборе апселл продуктов
        $upsellsContainer.on('change', '.wc-product-search', function() {
            updateUpsellOrder();
        });

        // Инициализируем начальное состояние
        updateUpsellOrder();
    });
    </script>
    <?php
}
add_action('admin_footer', 'add_upsell_order_script');

Что делает этот код:

  1. Сохраняет порядок апсейл продуктов именно в том порядке, в котором вы их выбираете
  2. Поддерживает этот порядок при отображении на фронтенде

Как это работает:

  1. При выборе апсейл продуктов в админке, порядок выбора автоматически сохраняется
  2. Этот порядок сохраняется в специальном мета-поле продукта
  3. При отображении на сайте, продукты показываются в том же порядке, в котором были выбраны
  4. Код подробно прокомментирован

Как использовать:

  1. Добавьте этот код в файл functions.php вашей темы или в плагин для кастомизации
  2. Перейдите к редактированию продукта
  3. Добавьте апсейл продукты в том порядке, в котором хотите их видеть
  4. Сохраните продукт
Этой статьей хочу начать цикл маленьких лайфхаков для работы с WordPress и интернет-магазинами в частности.