george
  • 0
Новичок

Отображение сообщений, связанных с другими сообщениями, по термину таксономии?

  • 0

У меня есть настраиваемый тип сообщений для профилей музыкантов и таксономия для их местоположения (иерархически разделены на страны, а затем города). На отдельных страницах профиля музыканта мне нужно отобразить список музыкантов в том же городе (т.е. дочернюю таксономию). Также было бы хорошо отображать сообщения в одной и той же стране отдельно (родительская таксономия).

Проблема, по-видимому, заключается в динамическом извлечении таксономии, разделении родительской и дочерней таксономий и использовании их в новом цикле.

Я могу отобразить список таксономий и удалить ссылки…

$terms = get_the_term_list( $post->ID, 'locations', '', ', ', '' ) ;
echo strip_tags($terms);

… который возвращает такой результат: Нью-Йорк, США

И я могу легко перебирать сообщения по фиксированному значению таксономии…

<?php $my_query = new WP_Query( array( 'locations' => 'new-york', 'showposts' => 10 ) ); ?>
<?php while ($my_query->have_posts()) : $my_query->the_post(); ?>
<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endwhile; ?>

Но у меня возникли проблемы с объединением двух: насколько я могу судить, «get_the_term_list» не имеет возможности возвращать только одну таксономию, и, похоже, не существует таксономического эквивалента «get_the_category».

Любая помощь очень ценится!!!

Share
  1. Привет @George :

    В зависимости от того, сколько музыкантов вы ожидаете иметь в своей базе данных, вы можете либо использовать полный маршрут API (что обычно предпочтительнее, когда это целесообразно), если у вас будет их большое количество (тысячи?), вы могли бы пойти с некоторый пользовательский SQL, чтобы получить именно те записи, которые вам нужны.

    Использование подхода WordPress API

    Основы подхода WordPress API заключаются в том, чтобы сначала вызвать wp_get_object_terms() ваш $post->ID профиль музыканта и вашу 'locations' таксономию, которая вернет список объектов «term». (К сожалению, вам нужно, чтобы это было только одно местоположение, иначе это решение развалится. Но игнорирование этого…)

    Затем вы берете идентификатор первого термина и передаете его вместе со своей 'locations' таксономией, get_objects_in_term() которая возвращает массив идентификаторов сообщений, у которых есть термины, связанные с желаемой таксономией. (Обратите внимание, что это будет включать ВСЕ сообщения, которые имеют ЛЮБОЙ термин, связанный с вашей 'locations' таксономией, поэтому этот подход хорош только для меньшего количества записей.)

    Затем вы создаете WP_Query объект, передавая ему запрос, который используется post__in для фильтрации по списку идентификаторов музыкантов, которые вы получили выше, а также по вашей 'locations' таксономии и конкретному городскому термину, полученному для вашего профилированного музыканта. Конечно, вы также должны не забыть отфильтровать профилированного музыканта, используя 'post__not_in' аргумент.

    Все вместе я упаковал эту логику в функцию с именем get_posts_related_by_taxonomy(), исходный код которой вы можете увидеть здесь (я упустил несколько деталей, когда объяснял, но, надеюсь, они достаточно очевидны):

    function get_posts_related_by_taxonomy($post_id,$taxonomy,$args=array()) {
      $query = new WP_Query();
      $terms = wp_get_object_terms($post_id,$taxonomy);
      if (count($terms)) {
        // Assumes only one term for per post in this taxonomy
        $post_ids = get_objects_in_term($terms[0]->term_id,$taxonomy);
        $post = get_post($post_id);
        $args = wp_parse_args($args,array(
          'post_type' => $post->post_type, // The assumes the post types match
          'post__in' => $post_ids,
          'post__not_in' => $post->ID,
          'taxonomy' => $taxonomy,
          'term' => $terms[0]->slug,
        ));
        $query = new WP_Query($args);
      }
      return $query;
    }
    

    Теперь вы можете использовать эту функцию в своем собственном цикле, например:

    // This assumes that your musician profile record is in the $post variable
    $musicians = get_posts_related_by_taxonomy($post->ID,'locations');?>
    <ul>
    <?php while ($musicians->have_posts()): $musicians->the_post(); ?>
      <li><?php the_id(); ?> -- <?php the_title(); ?></li>
    <?php endwhile; ?>
    </ul>
    

    Использование прямого SQL-подхода

    Как я уже сказал, я предпочитаю WordPress API, когда он жизнеспособный. К сожалению, я думаю, что вы столкнетесь с проблемами производительности или памяти, если у вас будет даже достаточно большое количество музыкантов, и вы будете использовать подход, показанный выше.

    В качестве альтернативы производительности и экономии памяти вы можете использовать прямой SQL для замены всего, включая вызов get_objects_in_terms() в предыдущем примере. Хорошей новостью является то, что SQL прост и вряд ли столкнется с проблемами совместимости в будущем с новыми версиями WordPress, поскольку SQL использует только ссылки на первичные и внешние ключи, и это не изменится, если они полностью не обновят систему таксономии, что я думаю навряд ли.

    Используя SQL, я создал другую версию get_posts_related_by_taxonomy() функции, которую вы будете называть точно так же, как и первая версия. SQL распознает, что таблица wp_term_relationships просто должна быть объединена их общим term_taxonomy_id полем, которое будет связывать все записи музыкантов для данной пары место/ (таксономия) + город/ (термин). Затем присоединяем его кwp_term_taxonomy table, чтобы мы могли фильтровать таксономию, а также фильтровать по профилированному музыканту на одном конце отношения и фильтровать, чтобы убедиться, что ни один из связанных музыкантов не является профилированным музыкантом на другом конце отношения. Наконец, мы удостоверяемся, что связанные типы сообщений музыкантов равны типу сообщений нашего профилированного музыканта, чтобы вы могли избежать еще одного поиска, в этом случае мы избегаем вызова get_post() .

    Наши результаты из SQL представляют собой хороший простой массив идентификаторов сообщений, который мы снова можем использовать с post__in аргументом, WP_Query но на этот раз нам не нужно включать или фильтр post__not_in, и мы можем указать использовать, поскольку наш SQL-запрос уже обработал все эти.taxonomy term $args post_type 'any'

    Для второй версии вот код, который вам нужен:

    function get_posts_related_by_taxonomy($post_id,$taxonomy,$args=array()) {
      global $wpdb;
      $sql =<<<SQL
    SELECT
      related.object_id
    FROM
      {$wpdb->term_relationships} post
      INNER JOIN {$wpdb->term_taxonomy} link ON post.term_taxonomy_id = link.term_taxonomy_id
      INNER JOIN {$wpdb->term_relationships} related ON post.term_taxonomy_id = related.term_taxonomy_id
    WHERE 1=1
      AND link.taxonomy='%s'
      AND post.object_id=%d
      AND post.object_id<>related.object_id
      AND post.post_type==related.post_type
    SQL;
      $post_ids = $wpdb->get_col($wpdb->prepare($sql,$taxonomy,$post_id));
      $args = wp_parse_args($args,array(
        'post_type' => 'any',
        'post__in' => $post_ids,
      ));
      return new WP_Query($args);
    }
    

    И снова вы будете использовать эту вторую версию get_posts_related_by_taxonomy() точно так же, как и первую версию.

    Надеюсь это поможет!

    • 0
  2. Проверьте wp_get_object_terms() , это более общая функция и то, что get_the_category() используется внутри.

    • 0

Оставить ответ

You must login to add an answer.