분류법 및 post_type으로 용어 가져 오기


17

2 개의 맞춤 게시물 유형 '북마크'및 '스 니펫'과 공유 분류 체계 '태그'가 있습니다. get_terms ()를 사용하여 분류 체계의 모든 용어 목록을 생성 할 수 있지만 목록을 게시물 유형으로 제한하는 방법을 알 수 없습니다. 내가 기본적으로 찾고있는 것은 다음과 같습니다.

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

이것을 달성 할 수있는 방법이 있습니까? 아이디어는 대단히 감사합니다 !!

아, 난 WP 3.1.1에있다

답변:


11

하나의 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;

}

예! 이것은 내가 원하는 것을 정확하게 수행합니다.
Gavin Hewitt

print_r(get_terms_by_post_type(array('category') , array('event') ));Warning: Missing argument 2 for wpdb::prepare()
devo

나는 틀릴 수 있지만, 내 머리 꼭대기에서, 그 '결합'문이 효과가 있다고 생각하지 않습니다. 즉, 단일 값 배열을 통과 한 경우에만 작동합니다. 이는 준비 함수가 생성 된 모든 작은 따옴표를 이스케이프하고 각 전체 '결합'을 하나의 문자열로 간주하기 때문입니다.
Codesmith

14

그래서 내가 작업중 인 프로젝트에 대해 그런 것이 필요했습니다. 나는 단순히 사용자 정의 유형의 모든 게시물을 선택하는 쿼리를 작성한 다음 사용중인 분류 체계의 실제 용어가 무엇인지 확인합니다.

그런 다음 분류법의 모든 용어를 사용하여 get_terms() 다음 두 목록 모두에있는 만 사용하고 함수로 묶어서 완성했습니다.

그러나 ID보다 더 많은 것이 필요했습니다. 이름이 필요했기 때문에 $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;
    }
}

용법:

용어 ID 목록 만 필요한 경우 :

$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;
    }
}

(array) $args4 $ vars 대신에 사용하면 더 좋지 않을까요? 이렇게하면 인수를 던지는 순서에 신경 쓰지 않을 수 있으므로 다음과 같이 get_terms_by_post_type( $args = array( 'taxonomies', 'args', 'post_type', 'fields' => 'all') )함수 내에서 호출하십시오 $args['taxonomies']. 빈 값을 추가하지 않고 인수 순서를 기억해야합니다. 또한 double 대신 작은 따옴표를 사용하는 것이 좋습니다. 나는 그들이 5 배 더 빨리 벌어지는 것을 보았다.
카이저

1
@kaiser-큰 따옴표로 묶인 문자열을 구문 분석해야합니다. 여기서 작은 따옴표로 묶은 값은 항상 리터럴로 처리됩니다. 문자열에서 변수를 사용하는 경우 의미가 있고 큰 따옴표를 사용하는 것이 완벽하지만 변수가없는 문자열 값의 경우 작은 따옴표가 더 이상적입니다 (구문을 분석 할 필요가 없기 때문에). 대부분의 경우 밀리 초에 대해 다시 이야기하십시오).
t31os

@ t31os-절대적으로 맞습니다. 난 여전히 선호 'this is my mood: '.$value이상 "this is my mood: $value"때문에 가독성의. 속도에 관해서는 : 약간은 아닙니다-최대 5 번 측정되었습니다. 그리고 전체 테마에 큰 따옴표를 사용하면 많은 요청을 받으면 빠르게 인용 부호가 표시됩니다. 어쨌든 당신은 그것을 분명히했습니다.
카이저

@ t31os 아웃에 대한 논의가 나는 속도 다시 meassured "대를 '내가 잘못했다. 차이점은 다른 사람이 알아 차릴 수있는 것보다 훨씬 큽니다.
카이저

1
멋진 기능 +1! 2 오타 : $ taxonomies는 $ taxonomy 및 $ terms [] = $ c; $ terms 여야합니다 [] = $ t;
Rob Vermeer

8

난 당신이 통과 할 수있는 기능을 썼다 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);

7

좋은 질문과 확실한 답변.

terms_clauses 필터를 사용하여 @jessica의 접근 방식이 정말 마음에 들었습니다. get_terms 함수를 매우 합리적인 방식으로 확장하기 때문입니다.

내 코드는 @braydon의 일부 SQL을 사용하여 중복을 줄이기 위해 그녀의 아이디어를 계속합니다. 또한 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 = $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 ('". esc_sql( $post_types ). "') GROUP BY t.term_id";
  }
  return $clauses;
}
add_filter('terms_clauses', 'my_terms_clauses', 99999, 3);

get_terms에는 GROUPY BY에 대한 절이 없기 때문에 WHERE 절 끝에 추가해야했습니다. 필터 우선 순위가 매우 높게 설정되어 있습니다.


3

위 코드의 Gavin 버전과 작동하도록 get_terms 인수를 만들 수 없었지만 마지막으로 변경하여 수행했습니다.

$terms2 = get_terms( $taxonomy );

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

Bainternet의 원래 기능과 동일합니다.


1
현재 버전에서 수정되었습니다
Gavin Hewitt

0

@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;
    }
}

편집 : 수정 사항이 추가되었습니다. 그러나 어떻게 든 그것은 여전히 ​​나를 위해 작동하지 않습니다. 카운트에 여전히 잘못된 값이 표시됩니다.


그것은 다른 이야기이지만 while 루프에서 중복을 피할 때 셀 수 있습니다.
Bainternet

용어 개수 수정으로 답변을 업데이트했습니다.
Bainternet

1
자신의 질문에 구체적으로 답변하지 않는 한 후속 질문을 답변으로 추가하지 마십시오. 대신 원래 질문에 추가해야합니다.
t31os

1
@ t31os : 아 네, 추가를 추가하는 방법이 궁금합니다. 내 질문을 편집 할 생각이 없었습니다. 감사!
Gavin Hewitt

이것을 어떻게 부를 수 있습니까? print_r(get_terms_by_post_typea(array('event','category','',array()));이것은 Warning: Invalid argument supplied for foreach()라인을 제공 합니다foreach ($current_terms as $t){
devo

0

중복을 피하십시오 :

//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;
        }

1
이것이 문제를 해결하는 이유를 설명 할 수 있습니까? 답변 방법을 참조하십시오 .
brasofilo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.