वर्गीकरण और पोस्ट_टाइप द्वारा शर्तें प्राप्त करें


17

मेरे पास 2 कस्टम पोस्ट प्रकार 'बुकमार्क' और 'स्निपेट्स' और एक साझा टैक्सोनॉमी 'टैग' है। मैं get_terms () के साथ वर्गीकरण में सभी शर्तों की एक सूची तैयार कर सकता हूं, लेकिन मैं यह पता नहीं लगा सकता कि सूची को पोस्ट प्रकार तक कैसे सीमित किया जाए। मैं मूल रूप से क्या देख रहा हूँ कुछ इस तरह है:

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

क्या इसको हासिल करने के लिए कोई रास्ता है? विचारों की बहुत सराहना की जाती है !!

ओह, मैं WP 3.1.1 पर हूं

जवाबों:


11

यहाँ एक एसक्यूएल क्वेरी के साथ कुछ समान करने का एक और तरीका है:

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;

}

हाँ! यह वही करता है जो मैं चाहता हूं।
गेविन हेविट

print_r(get_terms_by_post_type(array('category') , array('event') ));शोWarning: Missing argument 2 for wpdb::prepare()
देव

मैं गलत हो सकता है, लेकिन मेरे सिर के ऊपर से, मुझे नहीं लगता कि वे 'ज्वाइन' स्टेटमेंट काम करेंगे - यानी, वे केवल तभी काम करेंगे जब सिंगल-वैल्यू एरे पास किया गया हो। ऐसा इसलिए है क्योंकि तैयार फ़ंक्शन सभी उत्पन्न सिंगल-कोट्स से बच जाएगा, और प्रत्येक पूरे 'ज्वाइन' को एक स्ट्रिंग पर विचार करेगा।
कोडस्मिथ

14

तो यह सिर्फ इतना होता है कि मुझे एक प्रोजेक्ट के लिए कुछ ऐसा चाहिए था, जिस पर मैं काम कर रहा हूं। मैंने केवल एक कस्टम प्रकार के सभी पदों का चयन करने के लिए एक क्वेरी लिखी है, फिर मैं जांचता हूं कि वे मेरे वर्गीकरण की वास्तविक शर्तें क्या हैं जो वे उपयोग कर रहे हैं।

तब मुझे उस टैक्सोनॉमी का उपयोग करने की सभी शर्तें मिलीं 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 के अतिरिक्त तर्कों का उपयोग करने की आवश्यकता है जैसे: ऑर्डरबाई, ऑर्डर, पदानुक्रम ...

$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 $ var की सूची के बजाय उपयोग करें ? यह आपको तर्क में फेंकने वाले आदेश की परवाह नहीं करने की अनुमति देता है, इसलिए कुछ ऐसा है get_terms_by_post_type( $args = array( 'taxonomies', 'args', 'post_type', 'fields' => 'all') )और फिर उन्हें फ़ंक्शन के अंदर बुलाएं $args['taxonomies']। इससे आपको खाली मूल्यों को जोड़ने और अपने तर्कों के आदेश को याद रखने में मदद मिलेगी। मैं भी दोहरे के बजाय एकल उद्धरण का उपयोग करने का सुझाव दूंगा। मैंने उन्हें पांच गुना तेजी से मधुमक्खी मारते देखा।
kaiser

1
@ कैसर - डबल उद्धृत स्ट्रिंग्स को पार्स किया जाना है, जहां एकल उद्धृत मूल्यों को हमेशा शाब्दिक माना जाता है। जब आप एक स्ट्रिंग में चर का उपयोग कर रहे हैं तो यह समझ में आता है और दोहरे उद्धरण चिह्नों का उपयोग करना पूरी तरह से ठीक है, लेकिन गैर-चर स्ट्रिंग मूल्यों के लिए एकल उद्धरण अधिक आदर्श हैं (क्योंकि उन्हें पार्स करने की आवश्यकता नहीं होगी) और थोड़ा तेज (हम) ज्यादातर मामलों में मिलीसेकंड के बारे में बात कर रहे हैं)।
t31os

@ t31os - बिल्कुल सही। मैं अभी भी पसंद करते हैं 'this is my mood: '.$valueअधिक "this is my mood: $value"पठनीयता की वजह से। जब यह गति की बात आती है: यह थोड़ा नहीं है - मैंने पांच बार तक नापा। और जब आप हर जगह अपने पूरे विषय में दोहरे उद्धरण चिह्नों का उपयोग करते हैं, तो जब आप बहुत सारे अनुरोध प्राप्त करते हैं, तो वे जल्दी से योग करेंगे। वैसे भी अच्छा है कि आप स्पष्ट कर दिया।
केसर

@ t31os एक चर्चा से मैंने "बनाम की गति को फिर से माप लिया 'और मैं गलत था। कुछ भी बाहर अंतर है किसी को भी नोटिस होगा।
kaiser

1
+1 अच्छा समारोह! 2 टाइपोस: $ टैक्सोनोमीज़ का उपयोग फ़ंक्शन में किया जाता है $ टैक्सोनॉमी और $ शर्तें [] = $ c; $ शर्तें होनी चाहिए [] = $ t;
रोब वर्मेयर

8

मैंने एक फ़ंक्शन लिखा है जो आपको फ़ंक्शन post_typeमें $argsसरणी में पास करने की अनुमति देता है get_terms():

SQL लिखने के लिए @ hbraydon को HT।

 /**
 * 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

शानदार सवाल और ठोस जवाब।

मुझे वास्तव में @jessica द्वारा terms_clauses फ़िल्टर का उपयोग करना पसंद है, क्योंकि यह 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 के पास GROUP BY के लिए कोई क्लॉज नहीं है, मुझे इसे WHERE क्लॉज के अंत में जोड़ना था। ध्यान दें कि मेरे पास फ़िल्टर प्राथमिकता बहुत उच्च सेट है, आशा है कि यह हमेशा अंतिम रहेगा।


3

मैं ऊपर कोड के गेविन संस्करण के साथ काम करने के लिए get_terms तर्क बनाने में असमर्थ था, लेकिन अंत में बदलकर किया

$terms2 = get_terms( $taxonomy );

सेवा

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

जैसा कि यह बैनटेनट के मूल कार्य में था।


1
वर्तमान संस्करण में इसे निर्धारित किया गया
गेविन हेविट

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

संपादित करें: फिक्स (तों) जोड़ा गया। लेकिन किसी तरह यह अभी भी मेरे लिए काम नहीं कर रहा है। गिनती अभी भी गलत मान दिखाती है।


यह एक अलग कहानी है, लेकिन जब आप लूप में डुप्लिकेट से बचते हैं तो आप गिनती कर सकते हैं।
बेनटर्नेट

मैंने अपने जवाब को एक टर्म काउंट फिक्स के साथ अपडेट किया।
बेनटर्नट

1
कृपया अनुवर्ती के रूप में अनुवर्ती कार्रवाई न करें, जब तक कि आप विशेष रूप से अपने प्रश्न का उत्तर नहीं दे रहे हैं , इसके बजाय मूल प्रश्न के अतिरिक्त परिवर्धन किया जाना चाहिए।
t31os

1
@ t31os: आह हां, मैं सोच रहा था कि एक अतिरिक्त कैसे जोड़ा जाए। मेरे सवाल के संपादन के बारे में नहीं सोचा। धन्यवाद!
गेविन हेविट

मैं इसे कैसे कह सकता हूं? 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
क्या आप बता सकते हैं कि यह समस्या क्यों हल करता है? देखें कैसे जवाब दें
ब्रासोफिलो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.