Пользовательская таксономия WP_Query для всех терминов в таксономии?


8

Есть ли простой способ запросить любые сообщения, которые помечены каким-либо термином из определенной таксономии?

Я знаю эту технику:

$custom_taxonomy_query = new WP_Query( 
 array(
  'taxonomy_name' => 'term_slug',
 )
);

Но я бы хотел передать вместо term_slug подстановочный знак, или, возможно, просто пустую строку. Тогда это даст мне все посты, которые помечены любым термином в этой таксономии, а не только одним конкретным термином.

Спасибо за вашу помощь, Дэйв

Ответы:



23

Я столкнулся с похожей ситуацией, Дэйв. Этот код помог мне. Это не самый скудный вариант в мире, но он хорошо выполняет свою работу:

// Get all term ID's in a given taxonomy
$taxonomy = 'taxonomy_name';
$taxonomy_terms = get_terms( $taxonomy, array(
    'hide_empty' => 0,
    'fields' => 'ids'
) );

// Use the new tax_query WP_Query argument (as of 3.1)
$taxonomy_query = new WP_Query( array(
    'tax_query' => array(
        array(
            'taxonomy' => $taxonomy,
            'field' => 'id',
            'terms' => $taxonomy_terms,
        ),
    ),
) );

Надеюсь, это поможет вам или кому-либо еще, сталкивающемуся с проблемой.

Kevin


Это было очень полезно для меня. Спасибо @kevinlearynet
— Tyrun

Все еще относительно сегодня
— user1676224

7

Нечто подобное может работать:

$ args = array (
    'post_type' => 'post',
    'tax_query' => массив (
        массив (
            'taxonomy' => 'your_custom_taxonomy',
            'operator' => 'EXISTS'
        ),
    ),
);
$ query = new WP_Query ($ args);

Вы в основном запрашиваете любую публикацию, назначенную любому термину в пределах your_custom_taxonomy.


4

Привет @ Дэйв Моррис:

Вы правы, WordPress решает, если у вас нет термина, они просто проигнорируют вашу таксономию.

Есть три (3) основных подхода, которые вы можете попробовать:

  1. Используйте полный SQL-запрос с $wpdb->get_results(),

  2. Получите список $post->IDs для всех сообщений в вашей таксономии, а затем передайте их, используя 'post__id'аргумент, или

  3. Аннотируйте SQL, используемый сWP_Query помощью одного из хуков, который позволяет вам добавить SQL, INNER JOINссылающийся на таблицы таксономии.

Я стараюсь избегать полного SQL в WordPress до тех пор, пока он либо не поможет, либо просто возвращает список идентификаторов. И в этом случае я бы не стал использовать список $post-IDs для использования с 'post__id'аргументом, потому что это может привести к проблемам с производительностью и даже к памяти, если у вас много постов. Так что это оставляет нас с # 3.

Я создал Расширяемый классWP_Query под названием , PostsByTaxonomyкоторый использует 'posts_join'крюк. Вы можете видеть это здесь:

class PostsByTaxonomy extends WP_Query {
  var $posts_by_taxonomy;
  var $taxonomy;
  function __construct($args=array()) {
    add_filter('posts_join',array(&$this,'posts_join'),10,2);
    $this->posts_by_taxonomy = true;
    $this->taxonomy = $args['taxonomy'];
    unset($args['taxonomy']);
    parent::query($args);
  }
  function posts_join($join,$query) {
    if (isset($query->posts_by_taxonomy)) {
      global $wpdb;
      $join .=<<<SQL
INNER JOIN {$wpdb->term_relationships} ON {$wpdb->term_relationships}.object_id={$wpdb->posts}.ID
INNER JOIN {$wpdb->term_taxonomy} ON {$wpdb->term_taxonomy}.term_taxonomy_id={$wpdb->term_relationships}.term_taxonomy_id
  AND {$wpdb->term_taxonomy}.taxonomy='{$this->taxonomy}'
SQL;
    }
    return $join;
  }
}

Вы бы назвали этот класс, как вы видите ниже. Аргумент 'taxonomy'является обязательным, но вы можете передать любые (все?) Другие ожидаемые параметры WP_Query, такие как 'posts_per_page':

$query = new PostsByTaxonomy(array(
  'taxonomy' => 'category',
  'posts_per_page' => 25,
));
foreach($query->posts as $post) {
  echo " {$post->post_title}\n";
}

Вы можете скопировать PostsByTaxonomyкласс в functions.phpфайл вашей темы или использовать его в .phpфайле плагина, который вы пишете.

Если вы хотите быстро его протестировать, я разместил в Gist автономную версию кода, которую вы можете загрузить и скопировать в корневой каталог вашего веб-сервера как test.php, изменить для своего варианта использования, а затем запросить в браузере, используя URL-адрес, например http://example.com/test.php,

ОБНОВИТЬ

Чтобы опустить Sticky Posts из постов, включенных в запрос, попробуйте это:

$query = new PostsByTaxonomy(array(
  'taxonomy' => 'category',
  'posts_per_page' => 25,
  'caller_get_posts' => true,
));

Или, если вам важно, чтобы PostsByTaxonomyкласс никогда не включал липкие посты, вы можете поместить его в конструктор:

  function __construct($args=array()) {
    add_filter('posts_join',array(&$this,'posts_join'),10,2);
    $this->posts_by_taxonomy = true;
    $this->taxonomy = $args['taxonomy'];
    $args['caller_get_posts'] = true     // No Sticky Posts
    unset($args['taxonomy']);
    parent::query($args);
  }

ОБНОВЛЕНИЕ 2

После публикации вышеизложенного я узнал, что 'caller_get_posts' устарела и 'ignore_sticky_posts'будет использоваться в WordPress 3.1.


Майк, спасибо за твою помощь. Я не могу заставить это работать по какой-то причине. Он не возвращает только сообщения с условиями, назначенными из моей пользовательской таксономии. Кажется, всегда возвращаются другие посты. Однако он не возвращает все сообщения, поэтому он определенно что-то делает ... Могу ли я использовать функцию $ query-> have_posts () для итерации? Ни один из методов, кажется, не работает для меня, так или иначе.
— Дейв Моррис

Ах, это интересно. Я нашел запрос в журнале mysql, который получает два ожидаемых сообщения, и это работает. Но по какой-то причине пять сообщений возвращаются, когда я зацикливаюсь на $ query-> posts. Единственное, что я замечаю, это то, что непосредственно после выполнения запроса пользовательских записей таксономии выполняется другой запрос, который захватывает еще три сообщения по их post_id. И тогда я предполагаю, что все пять постов помещены в один массив результатов.
— Дейв Моррис

Я думаю, что я понял это. Этот пользовательский запрос, кажется, включает в себя липкие сообщения, даже если они не входят в эту пользовательскую таксономию. Любые идеи о том, как правильно соблюдать липкие сообщения, или, по крайней мере, чтобы получить их из этого конкретного запроса? Спасибо, Дейв
— Дейв Моррис

Ну, они "липкие" , верно? :) Это странное поведение, я думаю, но если вы используете, caller_get_posts=1и они должны уйти: codex.wordpress.org/Function_Reference/… Надеюсь, это поможет.
— MikeSchinkel

Это if(isset($query->posts_by_taxonomy))хорошая уловка, чтобы объединить объектно-ориентированную методологию с методологией ловушек WordPress.
— Ян Фабри

1

Вы должны просто иметь возможность установить таксономию и отказаться от включения термина.

Например.

<?php
$your_query = new WP_query;
$your_query->query( array( 'taxonomy' => 'your-taxonomy-name' ) );
?>

Это было бы почти так же, как запрос, выполняемый архивом таксономии.


Это не работает
— Дейв Моррис

Строка 1432 файла query.php проверяет, является ли таксономия ИЛИ термин пустым, поэтому вы не можете просто не пропустить слаг ... Какие-нибудь другие идеи?
— Дейв Моррис

@ t31os - Это может быть первая реакция; Я на самом деле был сбит с толку не раз, так как постоянно забываю. Но @Dave Моррис прав; если это не пара таксономии / термина, то WP_Queryпросто выбрасываете ее.
— MikeSchinkel

6
@ t31os - Да, WP_Queryк сожалению, не так элегантно. Это почти 1200 строк жестко закодированных особых случаев.
— MikeSchinkel

3
«почти 1200 строк жестко закодированных особых случаев». ... это сделало меня лол, пришлось +1 комментарий ...;)
— t31os
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.