gavinhewitt
  • 0
Новичок

Получить термины по таксономии И post_type

  • 0

У меня есть 2 пользовательских типа сообщений «закладки» и «фрагменты» и общий тег таксономии. Я могу создать список всех терминов в таксономии с помощью get_terms(), но я не могу понять, как ограничить список типом записи. В основном я ищу что-то вроде этого:

get_terms(array('taxonomy' => 'tag', 'post_type' => 'snippet'));

Есть ли способ добиться этого? Идеи приветствуются!!

О, я на WP 3.1.1

Share
  1. Вот еще один способ сделать что-то подобное с помощью одного SQL-запроса:

    static public function get_terms_by_post_type( $taxonomies, $post_types ) {
    
        global $wpdb;
    
        $query = $wpdb->prepare(
            "SELECT t.*, COUNT(*) from $wpdb->terms AS t
            INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id
            INNER JOIN $wpdb->term_relationships AS r ON r.term_taxonomy_id = tt.term_taxonomy_id
            INNER JOIN $wpdb->posts AS p ON p.ID = r.object_id
            WHERE p.post_type IN('%s') AND tt.taxonomy IN('%s')
            GROUP BY t.term_id",
            join( "', '", $post_types ),
            join( "', '", $taxonomies )
        );
    
        $results = $wpdb->get_results( $query );
    
        return $results;
    
    }
    
    • 0
  2. Так уж получилось, что мне нужно было что-то подобное для проекта, над которым я работаю. Я просто написал запрос, чтобы выбрать все сообщения пользовательского типа, а затем я проверяю, какие фактические термины моей таксономии они используют.

    Затем я использовал все термины этой таксономии, get_terms() а затем использовал только те, которые были в обоих списках, завернул их в функцию, и все готово.

    Но затем мне нужно было больше, чем просто идентификаторы: мне нужны были имена, поэтому я добавил новый аргумент с именем $fields, чтобы я мог указать функции, что возвращать. Затем я понял, что get_terms он принимает много аргументов, и моя функция была ограничена простыми терминами, которые используются типом записи, поэтому я добавил еще одно if утверждение, и вот оно:

    Функция:

    /* get terms limited to post type 
     @ $taxonomies - (string|array) (required) The taxonomies to retrieve terms from. 
     @ $args  -  (string|array) all Possible Arguments of get_terms http://codex.wordpress.org/Function_Reference/get_terms
     @ $post_type - (string|array) of post types to limit the terms to
     @ $fields - (string) What to return (default all) accepts ID,name,all,get_terms. 
     if you want to use get_terms arguments then $fields must be set to 'get_terms'
    */
    function get_terms_by_post_type($taxonomies,$args,$post_type,$fields = 'all'){
        $args = array(
            'post_type' => (array)$post_type,
            'posts_per_page' => -1
        );
        $the_query = new WP_Query( $args );
        $terms = array();
        while ($the_query->have_posts()){
            $the_query->the_post();
            $curent_terms = wp_get_object_terms( $post->ID, $taxonomy);
            foreach ($curent_terms as $t){
              //avoid duplicates
                if (!in_array($t,$terms)){
                    $terms[] = $c;
                }
            }
        }
        wp_reset_query();
        //return array of term objects
        if ($fields == "all")
            return $terms;
        //return array of term ID's
        if ($fields == "ID"){
            foreach ($terms as $t){
                $re[] = $t->term_id;
            }
            return $re;
        }
        //return array of term names
        if ($fields == "name"){
            foreach ($terms as $t){
                $re[] = $t->name;
            }
            return $re;
        }
        // get terms with get_terms arguments
        if ($fields == "get_terms"){
            $terms2 = get_terms( $taxonomies, $args );
            foreach ($terms as $t){
                if (in_array($t,$terms2)){
                    $re[] = $t;
                }
            }
            return $re;
        }
    }
    

    Применение:

    Если вам нужен только список идентификаторов терминов, то:

    $terms = get_terms_by_post_type('tag','','snippet','ID');
    

    Если вам нужен только список названий терминов, то:

    $terms = get_terms_by_post_type('tag','','snippet','name');
    

    Если вам нужен только список объектов терминов, то:

    $terms = get_terms_by_post_type('tag','','snippet');
    

    И если вам нужно использовать дополнительные аргументы get_terms, такие как: orderby, order, hierarchical…

    $args = array('orderby' => 'count', 'order' => 'DESC',  'hide_empty' => 1);
    $terms = get_terms_by_post_type('tag',$args,'snippet','get_terms');
    

    Наслаждаться!

    Обновлять:

    Чтобы зафиксировать количество терминов для конкретного изменения типа публикации:

    foreach ($current_terms as $t){
              //avoid duplicates
                if (!in_array($t,$terms)){
                    $terms[] = $t;
                }
            }
    

    к:

    foreach ($current_terms as $t){
        //avoid duplicates
        if (!in_array($t,$terms)){
            $t->count = 1;
            $terms[] = $t;
        }else{
            $key = array_search($t, $terms);
            $terms[$key]->count = $terms[$key]->count + 1;
        }
    }
    
    • 0
  3. Отличный вопрос и четкие ответы.

    Мне очень понравился подход @jessica с использованием фильтра terms_clauses, потому что он очень разумно расширяет функцию get_terms.

    Мой код является продолжением ее идеи, с небольшим количеством sql от @braydon для уменьшения дубликатов. Он также позволяет использовать массив post_types:

    /**
     * my_terms_clauses
     *
     * filter the terms clauses
     *
     * @param $clauses array
     * @param $taxonomy string
     * @param $args array
     * @return array
     **/
    function my_terms_clauses($clauses, $taxonomy, $args)
    {
      global $wpdb;
    
      if ($args['post_types'])
      {
        $post_types = implode("','", array_map('esc_sql', (array) $args['post_types']));
    
        // allow for arrays
        if ( is_array($args['post_types']) ) {
          $post_types = implode( "','", $args['post_types'] );
        }
        $clauses['join'] .= " INNER JOIN $wpdb->term_relationships AS r ON r.term_taxonomy_id = tt.term_taxonomy_id INNER JOIN $wpdb->posts AS p ON p.ID = r.object_id";
        $clauses['where'] .= " AND p.post_type IN ('". $post_types. "') GROUP BY t.term_id";
      }
      return $clauses;
    }
    add_filter('terms_clauses', 'my_terms_clauses', 99999, 3);
    

    Поскольку в get_terms нет предложения для GROUPY BY, мне пришлось добавить его в конец предложения WHERE. Обратите внимание, что у меня установлен очень высокий приоритет фильтра, в надежде, что он всегда будет последним.

    • 0
  4. Я написал функцию, которая позволяет передать массив в post_type функцию :$args get_terms()

    HT @braydon за написание SQL.

     /**
     * terms_clauses
     *
     * filter the terms clauses
     *
     * @param $clauses array
     * @param $taxonomy string
     * @param $args array
     * @return array
    **/
    function terms_clauses($clauses, $taxonomy, $args)
    {
        global $wpdb;
    
        if ($args['post_type'])
        {
            $clauses['join'] .= " INNER JOIN $wpdb->term_relationships AS r ON r.term_taxonomy_id = tt.term_taxonomy_id INNER JOIN $wpdb->posts AS p ON p.ID = r.object_id";
            $clauses['where'] .= " AND p.post_type='{$args['post_type']}'"; 
        }
        return $clauses;
    }
    add_filter('terms_clauses', 'terms_clauses', 10, 3);
    
    • 0
  5. Мне не удалось заставить аргументы get_terms работать с версией кода Гэвина, приведенной выше, но, в конце концов, это удалось, изменив

    $terms2 = get_terms( $taxonomy );
    

    к

    $terms2 = get_terms( $taxonomy, $args );
    

    как это было в исходной функции от Bainternet.

    • 0
  6. @Bainternet: Спасибо! Мне пришлось немного изменить функцию, потому что она не работала (некоторые опечатки). Единственная проблема сейчас в том, что счетчик сроков выключен. Подсчет не учитывает тип сообщения, поэтому я не думаю, что вы можете использовать в этом get_terms().

    function get_terms_by_post_type($post_type,$taxonomy,$fields='all',$args){
        $q_args = array(
            'post_type' => (array)$post_type,
            'posts_per_page' => -1
        );
        $the_query = new WP_Query( $q_args );
    
        $terms = array();
    
        while ($the_query->have_posts()) { $the_query->the_post();
    
            global $post;
    
            $current_terms = get_the_terms( $post->ID, $taxonomy);
    
            foreach ($current_terms as $t){
                //avoid duplicates
                if (!in_array($t,$terms)){
                    $t->count = 1;
                    $terms[] = $t;
                }else{
                    $key = array_search($t, $terms);
                    $terms[$key]->count = $terms[$key]->count + 1;
                }
            }
        }
        wp_reset_query();
    
        //return array of term objects
        if ($fields == "all")
            return $terms;
        //return array of term ID's
        if ($fields == "ID"){
            foreach ($terms as $t){
                $re[] = $t->term_id;
            }
            return $re;
        }
        //return array of term names
        if ($fields == "name"){
            foreach ($terms as $t){
                $re[] = $t->name;
            }
            return $re;
        }
        // get terms with get_terms arguments
        if ($fields == "get_terms"){
            $terms2 = get_terms( $taxonomy, $args );
    
            foreach ($terms as $t){
                if (in_array($t,$terms2)){
                    $re[] = $t;
                }
            }
            return $re;
        }
    }
    

    РЕДАКТИРОВАТЬ: добавлены исправления. Но почему-то это все еще не работает для меня. Счетчик по-прежнему показывает неверное значение.

    • 0
  7. Избегайте дубликатов:

    //avoid duplicates
        $mivalor=$t->term_id;
        $arr=array_filter($terms, function ($item) use ($mivalor) {return isset($item->term_id) && $item->term_id == $mivalor;});
    
        if (empty($arr)){
        $t->count=1;
                $terms[] = $t;
            }else{
                $key = array_search($t, $terms);
                $terms[$key]->count = $terms[$key]->count + 1;
            }
    
    • 0

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

You must login to add an answer.