Используя wp_query, можно ли заказать таксономию?

Мой вопрос прост, я использую WP_Query для получения сообщений о настраиваемых типах по таксономии с использованием tax_query.

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

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

Любые указатели в правильном направлении?

Спасибо всем.

44 голоса | спросил yeope 8 PMpFri, 08 Apr 2011 19:44:50 +040044Friday 2011, 19:44:50

9 ответов


12

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

Таксономии - это способы группировки вещей. Таким образом, смысл иметь таксономию в отношении должностей действительно состоит в том, чтобы иметь термины в этой таксономии, которые распределяются между должностями. Если в таксономии были термины, которые использовались только на одном посту каждый, то это сделало бы таксономический вид бессмысленным. И если условия были разделены так, как они должны быть, то упорядочение им не принесло бы ничего особенно полезного.

То, что вы должны использовать в такой ситуации, - это мета-сообщение. Вы можете заказать по почте мета, и это уникально для каждого сообщения.

Изменить: при этом вы можете заказать таксономию, создав собственный SQL-запрос с использованием фильтра, вы просто не можете сделать это из немодифицированного WP_Query: http://scribu.net/wordpress/sortable-taxonomy-columns.html

Однако, если вам приходится прибегать к подобным вещам, тогда ваша структура проектирования данных в первую очередь ошибочна. «Термины» в таксономии не являются фактическими «данными». Сами термины не имеют неотъемлемого значения, они просто метки для конкретной группы, которую они описывают. Если вы рассматриваете их как значимые данные, тогда у вас есть основной недостаток дизайна.

Таксономии группируют вещи, назначая им термины. Эта группировка - это весь смысл таксономий, эти термины - просто красивые лица на группировке. Если у вас есть значимые метаданные для назначения должности, тогда вместо этого вы должны использовать мета-сообщение. И что вы можете заказывать, потому что post meta использует оба ключа и значения для хранения информации. С таксономией вы действительно только сохраняете ключи, а их значения являются сообщениями, сгруппированными вместе этим термином.

В долгосрочной перспективе все будет проще, если вы используете для этого правильный подход. Хотя я не говорю, что вы не можете сделать что-то странное с таксономией, вы в конце концов делаете все для себя труднее, используя это неправильно.

ответил Otto 8 PMpFri, 08 Apr 2011 20:20:29 +040020Friday 2011, 20:20:29
33

Принятый ответ на этот вопрос неприемлем. Нелогично предположить, что упорядочение по налогам «не имеет смысла». Ответ, который он дал, не имеет смысла.

Считайте наличие типа сообщения в меню. Тогда у вас есть таможенный налог «FoodCategories». Налог с FoodCategories имеет условия «Завтрак», «Обед» и «Ужин». Если вы отправляете запрос с использованием параметра tax_query, теперь у вас есть результирующий набор со всеми условиями, однако они упорядочены по дате публикации.

Чтобы получить правильный порядок из них, относительно их терминов, а затем, чтобы отобразить на переднем конце соответствующим образом, разделив сообщения на их различные категории, вам нужно пройти через результирующий набор, а затем запросить каждого пользователя post в наборе результатов, чтобы найти его термины и сравнить с текущим термином, фильтровать в массив и продолжать всюду. Затем вам нужно снова пропустить новый массив для отображения. Это неэффективно.

Было бы неплохо, если бы WP имел параметр «tax__in» orderby, так как он «post__in», но, поскольку он этого не делает, вам либо нужно сделать этот смешной процесс; самостоятельно настройте запрос с помощью фильтра posts_orderby и фильтра posts_join, чтобы настроить метод orderby и добавить термин в результирующий набор, соответственно; или вам нужно сделать новый запрос для каждого термина, который вы фильтруете в разделах html относительно этих терминов.

Наиболее эффективным было бы изменение строки запроса с помощью фильтров. Проще всего было бы сделать три отдельных запроса. WP API должен обрабатывать заказы по налогам или любые ограничительные параметры запроса. Если вы ограничиваете запрос на основе определенных условий, существует высокая вероятность того, что многим придется заказывать те же условия.

ответил Aryan Duntley 28 J000000Monday14 2014, 15:36:51
13

Да, но это довольно активно ...

Добавьте к функции.php в теме:

function orderby_tax_clauses( $clauses, $wp_query ) {
    global $wpdb;
    $taxonomies = get_taxonomies();
    foreach ($taxonomies as $taxonomy) {
        if ( isset( $wp_query->query['orderby'] ) && $taxonomy == $wp_query->query['orderby'] ) {
            $clauses['join'] .=<<<SQL
LEFT OUTER JOIN {$wpdb->term_relationships} ON {$wpdb->posts}.ID={$wpdb->term_relationships}.object_id
LEFT OUTER JOIN {$wpdb->term_taxonomy} USING (term_taxonomy_id)
LEFT OUTER JOIN {$wpdb->terms} USING (term_id)
SQL;
            $clauses['where'] .= " AND (taxonomy = '{$taxonomy}' OR taxonomy IS NULL)";
            $clauses['groupby'] = "object_id";
            $clauses['orderby'] = "GROUP_CONCAT({$wpdb->terms}.name ORDER BY name ASC) ";
            $clauses['orderby'] .= ( 'ASC' == strtoupper( $wp_query->get('order') ) ) ? 'ASC' : 'DESC';
        }
    }
    return $clauses;
}

    add_filter('posts_clauses', 'orderby_tax_clauses', 10, 2 );

Это frankensteined от некоторых найденных вещей и некоторых вещей, которые я сделал сам. Объяснение довольно сложно, но в итоге это работает, вы можете поставить orderby = (таксономический запрос var) и порядок = ASC (или DESC), и она сразу же выйдет!

ответил Drew Gourley 8 PMpFri, 08 Apr 2011 20:36:19 +040036Friday 2011, 20:36:19
6

Я задерживаюсь в игре здесь, но есть более простой способ WordPressy сделать это.

Создайте свой налоговый запрос, как обычно.

$tax_query = array();
$tax_query['relation']="OR";
$tax_query[] = array(
    'taxonomy' => 'product_cat',
    'field'    => 'slug',
    'terms'    => $cat_terms,
);
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;

Настройте свои аргументы для query_posts или WP_Query

$args = array(
    'post_type'=>'post',
    'posts_per_page'=>12,
    'paged'=>$paged,
    'tax_query' => $tax_query,
);

Прежде чем сделать запрос query_posts /WP_Query, подключитесь к фильтру orderby и отмените его

add_filter('posts_orderby', 'edit_posts_orderby');
function edit_posts_orderby($orderby_statement) {
    $orderby_statement = " term_taxonomy_id ASC ";
    return $orderby_statement;
}
query_posts($args);
remove_filter('posts_orderby', 'edit_posts_orderby');

не забудьте удалить фильтр потом ...

это работает b /c tax_query создает для вас соединения и т. д., вам просто нужно заказать одно из полей из соединения.

ответил Francis Yaconiello 31 +03002014-10-31T16:48:14+03:00312014bEurope/MoscowFri, 31 Oct 2014 16:48:14 +0300 2014, 16:48:14
2

Хорошо, я бы хотел разоблачить свой опыт в сортировке пользовательских типов сообщений по категориям /таксономии.

WEB

  1. Веб-сайт туристического агентства, работающий на WordPress
  2. Основное содержание в пользовательском типе сообщений, называемом «truta»
  3. Таксономия с этой структурой Тип путешествия> страны континента.

СЛУЧАЙ

В страницах списка категорий архивов клиент хотел, чтобы сообщения сортировались по

  1. Континент, упорядоченный по количеству маршрутов на каждом из них.
  2. Страна, заказанная в алфавитном порядке.

ШАГИ

Сначала , я улавливаю запрос из запроса немодифицированной страницы архива, который был таким:

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_term_relationships.term_taxonomy_id IN (5,6,7,8,9,10,11,12,13,15,16,17,18,19,20,21,22,23,25,26,28,29,31,32,33,35,38,95,101,102,193) )
AND wp_posts.post_type IN ('ruta', 'nav_menu_item') 
AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 45 
AND wp_posts.post_status = 'private') 
GROUP BY wp_posts.ID 
ORDER BY wp_posts.post_date DESC LIMIT 0, 20

Второй , я отредактировал код sql в Sequel Pro для базы данных, чтобы соответствовать моим потребностям. Я получаю это (да, возможно, это может быть улучшено: мой знание MySQL не является выдающимся):

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID, tt1.parent AS pare,
    (
    SELECT COUNT(*) 
    FROM  wp_posts
    INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
    INNER JOIN wp_term_taxonomy AS tt1 ON ( tt1.term_taxonomy_id =      wp_term_relationships.term_taxonomy_id )
    INNER JOIN wp_term_taxonomy AS tt2 ON ( tt2.term_taxonomy_id =  tt1.term_taxonomy_id )
    WHERE 1=1  
    AND tt1.parent = pare
    ) AS Total
FROM  wp_posts
INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
INNER JOIN wp_term_taxonomy AS tt1 ON ( tt1.term_taxonomy_id =      wp_term_relationships.term_taxonomy_id )
INNER JOIN wp_terms ON ( tt1.term_id = wp_terms.term_id )
WHERE 1=1  
AND ( wp_term_relationships.term_taxonomy_id IN (5,6,7,8,9,10,11,12,13,15,16,17,18,19,20,21,22,23,25,26,28,29,31,32,33,35,38,95,101,102,193) ) 
AND wp_posts.post_type IN ('ruta', 'nav_menu_item') 
AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 45 
AND wp_posts.post_status = 'private') 
GROUP BY wp_posts.ID 
ORDER BY
total DESC,
wp_terms.name  

Третий , я подключил запрос к файлу functions.php с тремя фильтрами: posts_fields, posts_join и posts_orderby

Код в functions.php:

function xc_query_fields( $fields ) {

   $fields = "wp_posts.ID, wp_posts.post_title, wp_terms.name, tt1.parent AS pare,
    (
    SELECT COUNT(*) 
    FROM  wp_posts
    INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
    INNER JOIN wp_term_taxonomy AS tt1 ON ( tt1.term_taxonomy_id = wp_term_relationships.term_taxonomy_id )
    INNER JOIN wp_term_taxonomy AS tt2 ON ( tt2.term_taxonomy_id = tt1.term_taxonomy_id )
    WHERE 1=1  
    AND tt1.parent = pare
    )
    AS Total";
     return $fields;
}


function xc_query_joins( $join ) {
$join .= "INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
   INNER JOIN wp_term_taxonomy AS tt1 ON ( tt1.term_taxonomy_id = wp_term_relationships.term_taxonomy_id )
   INNER JOIN wp_terms ON ( tt1.term_id = wp_terms.term_id )";
 return $join;
}


function xc_query_orderby( $join ) {
    $join = "total DESC, wp_terms.name ";
    return $join;
 }

Наконец Я вызвал фильтры из крюка pre_get_post в соответствии с некоторыми условиями

function filtra_queries( $query )
{

  if (  is_archive()  && $query->is_main_query() && !is_admin()  ) {

$rutes = array('viajes-privados', 'asia', 'africa', 'oceania', 'america', 'oriente-proximo');

if  ( in_array( $query->get('category_name'), $rutes ) ) 
  {
  add_filter( 'posts_fields', 'xc_query_fields' );
  add_filter( 'posts_join', 'xc_query_joins' );
  add_filter( 'posts_orderby', 'xc_query_orderby' );
}// end if in_array

  }// end if is_archive

}
 add_filter('pre_get_posts', 'filtra_queries');

Надеюсь, это поможет кому-то.

ответил Xavier Caliz 4 Jpm1000000pmSun, 04 Jan 2015 18:09:00 +030015 2015, 18:09:00
1

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

global $wpdb;

$taxonomies = array('my-tax-1', 'my-tax-2', 'my-tax-3');

$orderby = "'".implode("', '", array_keys($taxonomies))."'";
$id_sql = $GLOBALS['wp_query']->request;

$id_sql = preg_replace('/LIMIT\s+\d+\s?,?\s\d*/', '', $id_sql);
$id_sql = str_replace('SQL_CALC_FOUND_ROWS', '', $id_sql);

$term_sql = "SELECT
  tt.taxonomy AS `taxonomy`,
  t.name AS `term_name`,
  t.slug AS `term_slug`,
  count(*) AS `term_count`
FROM ({$id_sql}) p 
JOIN wp_term_relationships tr
  ON p.ID = tr.object_id
JOIN wp_term_taxonomy tt
  ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN wp_terms t
  ON tt.term_id = t.term_id
WHERE tt.taxonomy IN ({$orderby})
GROUP BY t.slug
ORDER BY
  FIELD(tt.taxonomy, {$orderby})"; // Add further specific ordering here

$results = $wpdb->get_results($term_sql, ARRAY_A);

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

Если вы просто хотите, чтобы сообщения затем меняли запрос на SELECT p.* и GROUP BY p.ID

ответил CodeShaman 24 MarpmFri, 24 Mar 2017 19:48:47 +03002017-03-24T19:48:47+03:0007 2017, 19:48:47
1

У меня была очень похожая проблема, с которой я столкнулся: я хочу заказать заказный архив пост-типа (журнальные статьи) по пользовательской таксономии (вопросам). Я никогда не делаю прямых запросов SQL на моем сайте - и обычно, если вы похожи на эти другие ответы, вам нужно пересмотреть свой подход.

ПРОБЛЕМЫ:

1) Wordpress не позволяет вам упорядочивать таксономии любым разумным способом.

2) Wordpress просто не позволяет orderby использовать таксономии на WP_Query после типа (как указано в Отто).

SOLUTIONS:

1) Сортировка таксономий лучше всего выполняется с помощью Пользовательский таксономический заказ NE . Он позволяет вам заказать таксономию через WYSIWYG в wp-admin, который не так, как я бы это сделал, но я не нашел ничего лучшего.

Когда вы настраиваете плагин, вы получите нечто похожее на то, что я здесь сделал. Обратите внимание на параметр Auto-sort Queries of this Taxonomy - установите для этого параметра Custom Order as Defined Above; это дает вам заказ, который вам нужен. Снимок экрана:

 Отображение пользовательского таксономического заказа NE

2) С помощью упорядоченной таксономии теперь вы можете создать серию вызовов WP_Query, которые выполняются через каждый термин, эффективно создавая архив, упорядоченный таксономией. Используйте get_terms() для создания массива всех налоговых терминов, затем запустите foreach за каждый термин. Это создает WP_Query для каждого элемента term, который будет возвращать все сообщения за данный термин, эффективно создавая архив, упорядоченный по таксономическому термину. Код для этого:

  // Get your terms and put them into an array
  $issue_terms = get_terms([
    'taxonomy' => 'issues',
    'hide_empty' => false,
  ]);

  // Run foreach over each term to setup query and display for posts
  foreach ($issue_terms as $issue_term) {
    $the_query = new WP_Query( array(
      'post_type' => 'post',
      'tax_query' => array(
        array(
          'taxonomy' => 'issues',
          'field' => 'slug',
          'terms' => array( $issue_term->slug ),
          'operator' => 'IN'
        )
      )
    ) );

    // Run loop over each query
    while($the_query->have_posts()) :
      $the_query->the_post();

      // YOUR TEMPLATE OUTPUT FOR EACH POST

    endwhile;
  }

Связанные чтения на этом сайте: Показать все сообщения в пользовательский тип сообщения, сгруппированный по пользовательской таксономии

ответил staypuftman 10 PMpMon, 10 Apr 2017 17:45:43 +030045Monday 2017, 17:45:43
1

Я не уверен, почему все решения здесь в значительной степени перехватывают его. Хорошо, это уже полвека назад, но сейчас я запускаю следующий код и работает:

   <?php // Default
    $wheels_args = array(
        'post_type' => 'wheels',
        'posts_per_page' => '96',
        'orderby' => 'taxonomy, name', // Just enter 2 parameters here, seprated by comma
        'order'=>'ASC'
    );
    $loop = new WP_Query($wheels_args);
    ?>

Это сортирует таксономии вашего CPT сначала по таксономии в алфавитном порядке и внутри этих групп таксономии по алфавиту.

ответил user3135691 6 J000000Thursday17 2017, 15:26:34
0

Это похоже на запрос перед запросом, но мы не будем беспокоиться, если мы не будем запрашивать слишком много сообщений ... Идея состоит в том, чтобы изменить основной запрос, поэтому нам даже не нужно обращаться к шаблонам и генерировать новые запросы и циклы ...

function grouped_by_taxonomy_main_query( $query ) {

    if ( $query->is_home() && $query->is_main_query() ) { // Run only on the homepage

        $post_ids = array();

        $terms = get_terms('my_custom_taxonomy');

        foreach ( $terms as $term ) {
            $post_ids = array_merge( $post_ids, get_posts( array( 
                'posts_per_page' => 4, // as you wish...
                'post_type' => 'my_custom_post_type', // If needed... Default is posts
                'fields' => 'ids', // we only want the ids to use later in 'post__in'
                'tax_query' => array( array( 'taxonomy' => $term->taxonomy, 'field' => 'term_id', 'terms' => $term->term_id, )))) // getting posts in the current term
            );
        }

        $query->query_vars['post_type'] = 'my_custom_post_type'; // Again, if needed... Default is posts
        $query->query_vars['posts_per_page'] = 16; // If needed...
        $query->query_vars['post__in'] = $post_ids; // Filtering with the post ids we've obtained above
        $query->query_vars['orderby'] = 'post__in'; // Here we keep the order we generated in the terms loop
        $query->query_vars['ignore_sticky_posts'] = 1; // If you dont want your sticky posts to change the order

    }
}

// Hook my above function to the pre_get_posts action
add_action( 'pre_get_posts', 'grouped_by_taxonomy_main_query' );
ответил Marcelo Viana 22 AMpSat, 22 Apr 2017 09:38:39 +030038Saturday 2017, 09:38:39

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132