Пользовательская таксономия 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.