WP get_terms и поле ACF

Вопрос или проблема

Пытаюсь добавить термины из другого таксономии к текущему термину. Кажется, что все работает, когда у меня несколько значений, но 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.

Что я пробовал

  1. Использовал оператор сравнения “IN” (не работает, во всяком случае с оператором ‘=’ несколько значений работает)
  2. Убедился, что $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 могут варьироваться по размеру. Это важно для интеграции различных таксономий и уменьшает вероятность ошибок в логике работы сайта при обновлении или создании новых терминов.

Оцените материал
Добавить комментарий

Капча загружается...