Вопрос или проблема
Пытаюсь добавить термины из другого таксономии к текущему термину. Кажется, что все работает, когда у меня несколько значений, но get_terms($args) возвращает 0, когда есть только одно значение.
Вот настройка.
Термин, который я хочу обновить, находится в настраиваемой таксономии ‘list’
Термин, который я хочу получить, из настраиваемой таксономии ‘listing-website’
Оба термина имеют одно и то же поле ACF multi-select, называемое ‘taxonomy_term_niche’.
Я перехожу к термину в таксономии ‘list’ и выбираю ‘taxonomy_term_niche’, при сохранении/обновлении/создании он извлекает список терминов с таким же нишем, как я только что выбрал, а затем устанавливает их для себя.
Все работает нормально, когда у меня есть несколько значений (как показано ниже в var_dump), и я получаю желаемые ID терминов.
Однако get_terms($args) возвращает 0 (как показано ниже в var_dump), когда я выбрал только 1 значение в поле ACF.
Что я пробовал
- Использовал оператор сравнения “IN” (не работает, во всяком случае с оператором ‘=’ несколько значений работает)
- Убедился, что $niche всегда является массивом
if (!is_array($niche)) {
$niche = array($niche);
}
Вопрос в том, как сделать так, чтобы это работало для одного значения, как оно работает, когда ‘taxonomy_term_nice’ возвращает несколько значений?
function match_and_update_listing_websites($term_id, $tt_id, $taxonomy) {
// Проверяем, работаем ли мы с таксономией 'list'
if ('list' !== $taxonomy) {
return;
}
// Получаем значение 'taxonomy_term_niche' текущего термина
$niche = get_field('taxonomy_term_niche', 'term_' . $term_id);
// echo '<pre>';
// var_dump($niche);
// echo '</pre>';
// die();
// var_dump возвращает
// array(1) {
// [0]=>
// string(7) "General"
// }
// Если нет значения ниши, ничего не делаем
if (!$niche) {
return;
}
// if (!is_array($niche)) {
// $niche = array($niche);
// }
// echo '<pre>';
// var_dump($niche);
// echo '</pre>';
// die();
// Запрос в таксономию 'listing-website' для терминов с подходящей 'taxonomy_term_niche'
$args = array(
'taxonomy' => 'listing-website',
'meta_query' => array(
array(
'key' => 'taxonomy_term_niche', // Убедитесь, что это соответствует вашему фактическому ключу поля ACF
'value' => $niche, // Значение от термина 'list'
'compare' => '=',
),
),
'fields' => 'ids' // Нам нужны только ID терминов
);
// echo '<pre>';
// var_dump($args);
// echo '</pre>';
// die();
// var_dump возвращает
// array(3) {
// ["taxonomy"]=>
// string(15) "listing-website"
// ["meta_query"]=>
// array(2) {
// [0]=>
// array(3) {
// ["key"]=>
// string(19) "taxonomy_term_niche"
// ["value"]=>
// array(1) {
// [0]=>
// string(7) "General"
// }
// ["compare"]=>
// string(2) "="
// }
// ["hide_empty"]=>
// bool(false)
// }
// ["fields"]=>
// string(3) "ids"
// }
// Получаем соответствующие термины 'listing-website'
$matching_listing_websites = get_terms($args); //id сайтов-списков
// когда у меня одно значение в $niche
// echo '<pre>';
// var_dump($matching_listing_websites);
// echo '</pre>';
// die();
// var_dump возвращает
// array(0) {
// }
//
// Когда у меня два или более значений в $niche
// array(2) {
// [0]=>
// int(4171)
// [1]=>
// int(4173)
// }
// Если есть совпадающие термины 'listing-website'
if (!is_wp_error($matching_listing_websites) && !empty($matching_listing_websites)) {
// Получаем текущее значение поля 'taxonomy_listing_websites' (массив ID терминов)
$existing_listing_websites = get_field('taxonomy_listing_websites', 'term_' . $term_id);
// Убеждаемся, что у нас есть массив и объединяем существующие ID с новыми
if ($existing_listing_websites) {
$existing_listing_websites_ids = wp_list_pluck($existing_listing_websites, 'term_id');
} else {
$existing_listing_websites_ids = array();
}
// Объединяем существующие ID с только что найденными (избегая дубликатов)
$updated_listing_websites = array_unique(array_merge($existing_listing_websites_ids, $matching_listing_websites));
wp_set_object_terms($term_id, $updated_listing_websites, 'listing-website');
}
}
add_action('edit_term', 'match_and_update_listing_websites', 10, 3); // Запускаем при обновлении термина
add_action('create_term', 'match_and_update_listing_websites', 10, 3); // Запускаем при создании термина
Ответ или решение
Проблема с кодом заключается в том, что WordPress не может корректно обрабатывать условия в meta_query
при использовании оператора сравнения '='
с массивом значений, особенно когда массив содержит только один элемент. Давайте разберем теорию, пример и применение для решения этой проблемы.
Теория
В WordPress, функции get_terms()
и meta_query
работают несколько специфично: оператор '='
обычно предназначен для сравнения единичного значения, а не массива. Когда массив содержит более одного значения, результаты могут вернуться корректно, так как WordPress интерпретирует это как запрос на любое из значений. Однако, в случае одиночного значения, сравнению требуется пересмотр, чтобы убедиться, что оно корректно отображает мутипликацию с данными, с которыми вы работаете.
Решение может заключаться в использовании оператора 'IN'
для обработки массива значений даже если массив содержит только одно значение. Это позволит гарантировать, что запрос сможет корректно находить соответствия, независимо от количества значений в массиве.
Пример
Вот как можно изменить ваш код, чтобы учесть эту характеристику:
function match_and_update_listing_websites($term_id, $tt_id, $taxonomy) {
if ('list' !== $taxonomy) {
return;
}
$niche = get_field('taxonomy_term_niche', 'term_' . $term_id);
if (!$niche) {
return;
}
// Приведение $niche к массиву, если это строка
if (!is_array($niche)) {
$niche = array($niche);
}
// Использование оператора 'IN' для обработки возможного массива значений
$args = array(
'taxonomy' => 'listing-website',
'hide_empty' => false,
'meta_query' => array(
array(
'key' => 'taxonomy_term_niche',
'value' => $niche,
'compare' => 'IN', // Использование оператора 'IN'
),
),
'fields' => 'ids',
);
$matching_listing_websites = get_terms($args);
if (!is_wp_error($matching_listing_websites) && !empty($matching_listing_websites)) {
$existing_listing_websites = get_field('taxonomy_listing_websites', 'term_' . $term_id);
if ($existing_listing_websites) {
$existing_listing_websites_ids = wp_list_pluck($existing_listing_websites, 'term_id');
} else {
$existing_listing_websites_ids = array();
}
$updated_listing_websites = array_unique(array_merge($existing_listing_websites_ids, $matching_listing_websites));
wp_set_object_terms($term_id, $updated_listing_websites, 'listing-website');
}
}
add_action('edit_term', 'match_and_update_listing_websites', 10, 3);
add_action('create_term', 'match_and_update_listing_websites', 10, 3);
Применение
С помощью изменения оператора на 'IN'
, вы разрешаете WordPress корректно обрабатывать массивы, независимо от их длины. Такое решение обеспечивает более стабильное выполнение запросов, особенно в тех случаях, когда массивы значений ACF могут варьироваться по размеру. Это важно для интеграции различных таксономий и уменьшает вероятность ошибок в логике работы сайта при обновлении или создании новых терминов.