Wordpress meta_query - фильтрация метаданных сериализованного массива ACF | NikonoroW.ru

Пока разрабатывал фильтр таксономий по полям ACF (Advanced Custom Fields) для одного из проектов, столкнулся со следующей проблемой. Мне нужно было вывести и сделать множественный выбор полей ACF с последующей фильтрацией данных после выбора пользователем разных вариантов. Выводил список категорий через функцию WordPress — get_terms($args); , затем выводил полученные категории через foreach.

Код следующий:

$args = array(
            'meta_query'    => array(
                'relation'      => 'AND',
                array(
                    'key'       => 'acf-filed-name',
                    'value'     => '$_GET['filter']['acf-field-name']',
                    'compare'   => 'LIKE'
                )
            )
);

$categories = get_terms($args);

Все в общем-то было хорошо, но когда в meta_query было несколько массивов, например, больше 4, то метод сравнения LIKE ломал сайт, так как нагрузка на сервер была колоссальная. Методы сравнения через = или другие сравнения не давали никакого результата.

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

Пример сохраненных в бд метаданных находится в сериализованном массиве, подобном приведенному ниже:

a:4:{i:0;s:7:"acf-field-name";i:1;s:15:"acf-field-two";i:2;s:4:"acf-more-v";i:3;s:14:"acf-type-f";}

В документации писали только про 2-3 массива, но не более и метод сравнения там был LIKE.

Решение проблемы:

$args = array(
    'meta_query'    => array(
        'relation'      => 'AND',
        array(
            'key'       => 'acf-field-name',
            'value'     => '"(' . implode('|', $_GET['filter']['acf-field-name']) . ')"',
            'compare'   => 'REGEXP'
        ),
        array(
            'key'       => 'acf-field-two',
            'value'     => '"(' . implode('|', $_GET['filter']['acf-field-two']) . ')"',
            'compare'   => 'REGEXP'
        )
    )
);

$categories = get_terms($args);

Поскольку метаданные сериализованы в столбце базы данных и технически представлены в виде строки, можно выполнить сравнение с помощью REGEXP.

Если ваши значения «value» содержат специальные символы, которые должны быть экранированы для корректного REGEXP, используйте функцию preg_quote. В противном случае это решение должно работать на все сто процентов.

Сравнение через REGEXP работает гораздо быстрее, чем LIKE и так сильно не нагружает сервер хостинга.

Протестировано на WordPress 6.2 (PHP 8.2).

Дата создания статьи: 08.05.2023

Рубрика: Веб-разработка

Комментарии

Оставьте Ваше сообщение

Подписаться
Уведомить о
guest
0 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии

Смотрите далее

Ознакомьтесь с другими работами

0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x
()
x