WP_Query Авторы ИЛИ категории

Я пытаюсь создать фид, где сообщения вытягиваются на основе множества авторов, или набора категорий, но мне не повезло. Я пробовал использовать meta_query и tax_query , но не работал. В основном запрос, который я пытаюсь запустить:

 "SELECT * FROM wp_posts WHERE author_id = $set_of_authors OR category = $set_of_categories" 

Я надеюсь получить объект сообщения, который я мог бы просто запустить через цикл, но я возьму то, что могу. Единственное, что я мог подумать, это запустить get_results с этим запросом, но я знаю, что это, как правило, не WordPress. Есть ли лучший способ получить этот запрос?

Solutions Collecting From Web of "WP_Query Авторы ИЛИ категории"

Пользовательский пул подачи

Чтобы создать настраиваемый пул подачи, например

 example.tld/billyfeed/ 

мы можем использовать add_feed() но мы должны add_feed() правила перезаписи, чтобы активировать его. Мы можем это сделать, например, посетив страницу настроек Permalinks в бэкэнд.

Чтобы создать фид, мы можем использовать, например, do_feed_rss2() или do_feed_atom() .

Вот пример:

 add_action( 'init', function() { add_feed( 'billyfeed', function() { do_feed_rss2(); }); }); 

Изменение пользовательского запроса фида

Затем нам нужно изменить наш пользовательский канал, чтобы мы либо получили авторов, либо категории .

Ниже приведено обходное решение с использованием фильтра posts_clauses но без замены строк с помощью str_replace() .

 /** * Custom feed example.tld/billyfeed that queries authors or categories * Supports pagination * * @link http://wordpress.stackexchange.com/a/207876/26350 */ add_filter( 'posts_clauses', function( $clauses, \WP_Query $q ) { //--------------------------------------- // Only target our custom feed //--------------------------------------- if( ! $q->is_feed( 'billyfeed' ) || ! $q->is_main_query() ) return $clauses; global $wpdb; //--------------------------------------- // Input - we edit this to our needs //--------------------------------------- $tax_query = [ [ 'taxonomy' => 'category', 'field' => 'slug', 'terms' => [ 'red', 'green', 'blue' ] ] ]; $author__in = [ 1, 2, 3 ]; //--------------------------------------- // Generate the tax query SQL //--------------------------------------- $qv = [ 'tax_query' => $tax_query, 'cat' => null, 'tag' => null ]; $q->parse_tax_query( $qv ); $tc = $q->tax_query->get_sql( $wpdb->posts, 'ID' ); //--------------------------------------- // Generate the author query SQL //--------------------------------------- $csv = join( ',', wp_parse_id_list( (array) $author__in ) ); $authors = " {$wpdb->posts}.post_author IN ( $csv ) "; //--------------------------------------- // Make sure the authors are set and // the tax query is valid (doesn't contain 0 = 1) //--------------------------------------- if( ! empty( $author__in ) && false === strpos ( $tc['where' ], ' 0 = 1' ) ) { // Append to the current join/where parts $clauses['join'] .= $tc['join']; $clauses['where'] .= sprintf( ' AND ( %s OR ( 1=1 %s ) ) ', // The tax query SQL comes prepended with AND $authors, $tc['where'] ); } return $clauses; }, PHP_INT_MAX, 2 ); 

где мы $tax_query и $author__in для наших нужд.

Это генерирует следующий основной запрос SQL:

 SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) WHERE 1=1 AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') AND ( wp_posts.post_authors IN (1,2,3 ) OR ( 1=1 AND ( wp_term_relationships.term_taxonomy_id IN (1,43,120) ) ) ) ORDER BY wp_posts.post_date DESC LIMIT 0, 10; 

При таком подходе мы все еще можем разбивать наш фид:

 example.tld/billyfeed/?paged=2 

Ну, это некрасиво, и я уверен, что есть лучшие способы сделать это, но это то, что я придумал:

 if ($author_ids) { $author_ids = implode(',', $author_ids); } if ($cat_ids) { $cat_ids = implode(',', $cat_ids); } global $wpdb; if (count($author_ids) > 0 && count($cat_ids) > 0) { $posts = $wpdb->get_results( "SELECT * FROM $wpdb->posts INNER JOIN $wpdb->term_relationships ON $wpdb->posts.ID = $wpdb->term_relationships.object_id WHERE post_status = 'publish' AND post_author IN ($author_ids) OR term_taxonomy_id IN ($cat_ids) ORDER BY post_date DESC" ); $post_ids = array(); foreach ($posts as $post) { if (!in_array($post->ID, $post_ids)) { $post_ids[] = intval($post->ID); } } $post_ids = array_slice($post_ids, 0, 12); $query = new WP_Query(array('post__in' => $post_ids)); } else if (count($author_ids > 0 ) && count($cat_ids) == 0) { $query = new WP_Query("author={$author_ids}&posts_per_page=12"); } else if (count($author_ids == 0 ) && count($cat_ids) > 0) { $query = new WP_Query("cat={$cat_ids}&posts_per_page=12"); } 

В этом конкретном случае я искал 12 сообщений, поэтому, если кому-то нужно больше, просто измените число 12 внизу на нужное число.

Я не уверен, почему, но эта строка:

  $post_ids = array_slice($post_ids, 0, 12); 

пришлось изменить на это:

  $post_ids = array_slice($post_ids, 0, 16); 

потому что он печатал только 8 сообщений вместо 12, несмотря на журналы, в которых говорилось, что мои $ post_ids содержат 12 почтовых идентификаторов. В любом случае, этот бит сам по себе не должен вызывать проблем для кого-либо, кто хочет его использовать. Надеюсь, это поможет или кто-то еще знает о лучшем способе реализовать это.