सिंगल - {$ पोस्ट_टाइप} - {स्लग}। कस्टम पोस्ट प्रकारों के लिए


20

Wordpress टेम्पलेट पदानुक्रम का मेरा पसंदीदा हिस्सा एक टेम्पलेट का चयन करने के लिए Wordpress में पृष्ठ को संपादित करने के बिना, स्लग द्वारा पृष्ठों के लिए टेम्पलेट फ़ाइलों को जल्दी से बनाने की क्षमता है।

वर्तमान में हम यह कर सकते हैं:

पृष्ठ- {स्लग} .php

लेकिन मैं ऐसा करने में सक्षम होना चाहता हूं:

एकल {post_type} - {} स्लग .php

इसलिए, उदाहरण के लिए, पोस्ट प्रकार में review, जिसे मैं "मेरा महान समीक्षा" नामक पोस्ट के लिए एक टेम्पलेट बना सकता हूंsingle-review-my-great-review.php

क्या किसी ने इसे पहले सेट किया है? single-{post_type}-{slug}.php


पहले कभी भी इस तरह के सेटअप का इस्तेमाल नहीं किया है, लेकिन अगर यह बहुत जटिल है, तो बस एक टेम्प्लेट फ़ाइल क्यों न बनाएं और इसे प्रश्न में समीक्षा के साथ जोड़ दें।
शेन

WP 3.4 स्वचालित रूप से प्राप्त होता है single-{post_type}-{slug}.php, इसलिए WP 3.4 में अपग्रेड करना एक और विकल्प है।
यितवैल

जवाबों:


19

A) कोर में आधार

जैसा कि आप कोडेक्स टेम्पलेट पदानुक्रम विवरण में देख सकते हैं , single-{$post_type}.phpपहले से ही समर्थित है।


बी) कोर पदानुक्रम का विस्तार

अब ख़ुशी से कुछ फ़िल्टर और हुक अंदर हैं /wp-includes/template-loader.php

  • do_action('template_redirect');
  • apply_filters( 'template_include', $template )
  • और: get_query_template( $type, ... )नाम के अंदर एक विशिष्ट फिल्टर :"$type}_template"

B.1) यह कैसे काम करता है

  1. टेम्प्लेट लोडर फ़ाइल के अंदर, टेम्प्लेट को क्वेरी var / wp_query सशर्त द्वारा लोड किया जाता है is_*():।
  2. तब सशर्त ट्रिगर होता है ("एकल" टेम्पलेट के मामले में): is_single() && $template = get_single_template()
  3. यह तब ट्रिगर करता है get_query_template( $type, $templates ), जहां $typeहैsingle
  4. फिर हमारे पास "{$type}_template"फिल्टर है

सी) समाधान

जैसा कि हम केवल एक टेम्पलेट के साथ पदानुक्रम का विस्तार करना चाहते हैं जो वास्तविक टेम्पलेट से पहले लोड हो जाता है "single-{$object->post_type}.php", हम पदानुक्रम को रोकेंगे और टेम्पलेट सरणी की शुरुआत में एक नया टेम्पलेट जोड़ेंगे।

// Extend the hierarchy
function add_posttype_slug_template( $templates )
{

    $object = get_queried_object();

    // New 
    $templates[] = "single-{$object->post_type}-{$object->post_name}.php";
    // Like in core
    $templates[] = "single-{$object->post_type}.php";
    $templates[] = "single.php";

    return locate_template( $templates );    
}
// Now we add the filter to the appropriate hook
function intercept_template_hierarchy()
{
    add_filter( 'single_template', 'add_posttype_slug_template', 10, 1 );
}
add_action( 'template_redirect', 'intercept_template_hierarchy', 20 );

नोट: (यदि आप डिफ़ॉल्ट ऑब्जेक्ट स्लग के अलावा कुछ उपयोग करना चाहते हैं) तो आपको $slugअपनी पर्मलिंक-संरचना के अनुसार समायोजित करना होगा । वैश्विक से आपको जो कुछ भी चाहिए, बस उपयोग करें (object) $post

Trac टिकट

जैसा कि उपरोक्त दृष्टिकोण वर्तमान में समर्थित नहीं है (आप केवल इस तरह से पूर्ण स्थित पथ को फ़िल्टर कर सकते हैं), यहां ट्रेक टिकट की एक सूची है:


मैं इसका परीक्षण करना चाहता हूं, लेकिन ऐसा लगता है कि अंत में आपके ऐड_फिल्टर लाइन में कुछ कमी है।
सुपर स्टार

@supertrue अच्छा कैच। :) )फिल्टर के अंदर एक और लापता मिला । फिक्स्ड। हो सकता है कि आप टेम्प्लेट के अंदर स्लग से पहले अंडरलाइन के साथ डैश का आदान-प्रदान करना चाहते हों। टेम्प्लेट को देखते समय प्रत्यय को बेहतर तरीके से खड़े होने दें।
kaiser

साइट पर इस त्रुटि का कारण बनता है : चेतावनी: array_unshift () [function.array-unshift]: पहला तर्क सरणी में एक सरणी होना चाहिए [array_unshift]
supertrue

ठीक है, लेकिन फिर कुछ और कोर टेम्पलेट्स को इंटरसेप्ट कर रहा है। फ़ंक्शन ठीक काम करता है और $templatesएक सरणी है। इस पास्टबिन (कोई समाप्ति तिथि नहीं) में मुख्य कार्य देखें । सुनिश्चित करें कि आप प्लगइन्स और डिफ़ॉल्ट थीम के बिना इंस्टॉल के साथ इसका परीक्षण करते हैं । फिर एक दूसरे को सक्रिय करें और देखें कि क्या त्रुटि अभी भी होती है।
कैसर

हाँ, मैंने इसे डीबग कर लिया है मुझे स्ट्रिंग के रूप में पहले पाए गए टेम्पलेट का अंतिम पूर्ण पथ मिलता है। उत्तर को बदलने से पहले, मुझे इसके बारे में कुछ कोर डेवलपर से बात करनी होगी। इसके अलावा: मैंने कुछ मिलाया: slugकेवल शर्तों और वर्गीकरण के लिए उपलब्ध है। आपको $post->post_nameअपनी पर्मलिंक संरचना के अनुकूल होने के साथ प्रतिस्थापित करना चाहिए । वर्तमान में आपके परमिशन स्ट्रक्चर और रीराइट नियमों के आधार पर पथ को पुनः प्राप्त करने और बदलने के साथ सभी मामलों के लिए स्वचालित रूप से ऐसा करने का कोई तरीका नहीं है। एक और अद्यतन की अपेक्षा करें।
कैसर

4

बाद खाका पदानुक्रम छवि , मैं इस तरह के एक विकल्प दिखाई नहीं देता।

तो कैसे मैं इसके बारे में जाना होगा heres:

समाधान 1 (मेरी राय में सर्वश्रेष्ठ)

एक टेम्प्लेट फ़ाइल बनाएं और उसे समीक्षा में संबद्ध करें

 <?php
 /*
 Template Name: My Great Review
 */
 ?>

अपनी थीम डायरेक्टरी में टेम्प्लेट php फाइल को जोड़ना, यह आपके पोस्ट के एडिट पेज में एक टेम्प्लेट विकल्प के रूप में दिखाई देगा।

समाधान २

यह संभवतः template_redirectहुक का उपयोग करके प्राप्त किया जा सकता है ।

Functions.php फ़ाइल में:

 function my_redirect()
 {
      global $post;

      if( get_post_type( $post ) == "my_cpt" && is_single() )
      {
           if( file_exists( get_template_directory() . '/single-my_cpt-' . $post->post_name . '.php' ) )
           {
                include( get_template_directory() . '/single-my_cpt-' . $post->post_name . '.php' );
                exit;
           }
      }
 }
 add_action( 'template_redirect', 'my_redirect' );

संपादित करें

जोड़ा गया file_existsचेक


तुम exit;वहाँ क्यों हो ?
kaiser

@kaiser उस समय जो कुछ भी ट्यूटोरियल में रहा होगा, अगर यह आवश्यक नहीं है तो मैं इसे हटा दूंगा।
शेन

1
@kaiser: exit()डिफ़ॉल्ट टेम्पलेट लोड करने से रोकने के लिए आवश्यक है।
scribu

समाधान 1 केवल पृष्ठों के लिए काम करेगा, न कि पदों के लिए।
IXN

2

शीर्ष उत्तर (4 साल पहले से) अब काम नहीं करता है, लेकिन वर्डप्रेस कोडेक्स का समाधान यहां है :

<?php
function add_posttype_slug_template( $single_template )
{
    $object = get_queried_object();
    $single_postType_postName_template = locate_template("single-{$object->post_type}-{$object->post_name}.php");
    if( file_exists( $single_postType_postName_template ) )
    {
        return $single_postType_postName_template;
    } else {
        return $single_template;
    }
}
add_filter( 'single_template', 'add_posttype_slug_template', 10, 1 );
?>

1

पेज टेम्पलेट का उपयोग करें

स्केलेबिलिटी के लिए एक और तरीका यह होगा कि आप pageअपने कस्टम पोस्ट टाइप के लिए पोस्ट टाइप पर पेज टेम्पलेट ड्रॉप-डाउन कार्यक्षमता को डुप्लिकेट करें ।

पुन: प्रयोज्य कोड

कोड में डुप्लीकेशन एक अच्छा अभ्यास नहीं है। ओवरटाइम करने पर यह एक कोडबेस के लिए गंभीर ब्लोट का कारण बन सकता है जब तब किसी डेवलपर के लिए इसे प्रबंधित करना बहुत मुश्किल हो जाता है। हर एक स्लग के लिए एक टेम्प्लेट बनाने के बजाय, आपको सबसे अधिक एक-से-कई टेम्प्लेट की आवश्यकता होगी जो कि एक-से-एक पोस्ट-टू-टेम्प्लेट के बजाय पुन: उपयोग किए जा सकते हैं।

कोड

# Define your custom post type string
define('MY_CUSTOM_POST_TYPE', 'my-cpt');

/**
 * Register the meta box
 */
add_action('add_meta_boxes', 'page_templates_dropdown_metabox');
function page_templates_dropdown_metabox(){
    add_meta_box(
        MY_CUSTOM_POST_TYPE.'-page-template',
        __('Template', 'rainbow'),
        'render_page_template_dropdown_metabox',
        MY_CUSTOM_POST_TYPE,
        'side', #I prefer placement under the post actions meta box
        'low'
    );
}

/**
 * Render your metabox - This code is similar to what is rendered on the page post type
 * @return void
 */
function render_page_template_dropdown_metabox(){
    global $post;
    $template = get_post_meta($post->ID, '_wp_page_template', true);
    echo "
        <label class='screen-reader-text' for='page_template'>Page Template</label>
            <select name='_wp_page_template' id='page_template'>
            <option value='default'>Default Template</option>";
            page_template_dropdown($template);
    echo "</select>";
}

/**
 * Save the page template
 * @return void
 */
function save_page_template($post_id){

    # Skip the auto saves
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
        return;
    elseif ( defined( 'DOING_AJAX' ) && DOING_AJAX )
        return;
    elseif ( defined( 'DOING_CRON' ) && DOING_CRON )
        return;

    # Only update the page template meta if we are on our specific post type
    elseif(MY_CUSTOM_POST_TYPE === $_POST['post_type'])
        update_post_meta($post_id, '_wp_page_template', esc_attr($_POST['_wp_page_template']));
}
add_action('save_post', 'save_page_template');


/**
 * Set the page template
 * @param string $template The determined template from the WordPress brain
 * @return string $template Full path to predefined or custom page template
 */
function set_page_template($template){
    global $post;
    if(MY_CUSTOM_POST_TYPE === $post->post_type){
        $custom_template = get_post_meta($post->ID, '_wp_page_template', true);
        if($custom_template)
            #since our dropdown only gives the basename, use the locate_template() function to easily find the full path
            return locate_template($custom_template);
    }
    return $template;
}
add_filter('single_template', 'set_page_template');

यह थोड़ा देर से जवाब है, लेकिन मुझे लगा कि यह मूल्यवान होगा क्योंकि वेब पर किसी ने भी इस दृष्टिकोण को प्रलेखित नहीं किया है जहां तक ​​मैं बता सकता हूं। आशा है कि यह किसी को बाहर करने में मदद करता है।


1

मेरे मामले में, मेरे पास एल्बम और ट्रैक कस्टम पोस्ट प्रकार हैं जो एक एल्बम वर्गीकरण द्वारा लिंक किए गए हैं। मैं एल्बम और ट्रैक पोस्ट के लिए उनके एल्बम वर्गीकरण के आधार पर अलग-अलग एकल टेम्पलेट्स का उपयोग करने में सक्षम होना चाहता था।

ऊपर कैसर के उत्तर के आधार पर, मैंने यह कोड लिखा था। यह अच्छा काम करता है।
ध्यान दें। मुझे add_action () की आवश्यकता नहीं थी।

// Add an additional template option to the template hierarchy
add_filter( 'single_template', 'add_albumtrack_taxslug_template', 10, 1 );
function add_albumtrack_taxslug_template( $orig_template_path )
{
    // at this point, $orig_template_path is an absolute located path to the preferred single template.

    $object = get_queried_object();

    if ( ! (
        // specify another template option only for Album and Track post types.
        in_array( $object->post_type, array( 'gregory-cpt-album','gregory-cpt-track' )) &&
        // check that the Album taxonomy has been registered.
        taxonomy_exists( 'gregory-tax-album' ) &&
        // get the Album taxonomy term for the current post.
        $album_tax = wp_get_object_terms( $object->ID, 'gregory-tax-album' )
        ))
        return $orig_template_path;

    // assemble template name
    // assumption: only one Album taxonomy term per post. we use the first object in the array.
    $template = "single-{$object->post_type}-{$album_tax[0]->slug}.php";
    $template = locate_template( $template );
    return ( !empty( $template ) ? $template : $orig_template_path );
}

अब मैं सिंगल-ग्रेगरी-सीपीटी-ट्रैक-टैक्स-सेरेन्डिपिटी.फपी और सिंगल-ग्रैगोरी-केप्ट-एल्बम-टैक्स-सेरेन्डिपिटी.फपी नाम के टेम्प्लेट बना सकता हूं और WP उन्हें स्वचालित रूप से उपयोग करेगा; 'टैक्स-सेरेन्डिपिटी' पहला एल्बम टैक्सोनॉमी शब्द का स्लग है।

संदर्भ के लिए, 'single_template' फ़िल्टर हुक में घोषित किया गया है:
/wp-includes/theme.php:get_query_template()

नमूना कोड के लिए धन्यवाद कैसर।

चीयर्स, ग्रेगरी


हाय ग्रेग - WPSE में आपका स्वागत है। कृपया प्रश्नों के उत्तर के रूप में केवल उत्तर पोस्ट करें - प्रश्नों का पालन न करें। यदि आपके पास एक प्रश्न है जिसका उत्तर किसी मौजूदा उत्तर से नहीं है और एक टिप्पणी के लिए बहुत बड़ा है, तो कृपया एक और प्रश्न खोलें :)
स्टीफन हैरिस

1
स्ट्रिंग / सरणी प्रश्न को हटा दिया गया है :-)
ग्रेगरी

1
"नमूना कोड के लिए धन्यवाद कैसर।" - आपका स्वागत है।
केसर

क्या यह आपके लिए काम करता है? सबसे पहले, आपके कोड में '$ टेम्पलेट' पर टिप्पणी नहीं की जानी चाहिए .. और मुझे लगता है कि '$ एल्बम_टैक्स [0] -> स्लग' के बजाय '$ ऑब्जेक्ट-> पोस्ट_नाम' होना चाहिए, है ना?
ग्रैग्मेटिस

$ टेम्पलेट लाइन तय की। धन्यवाद। $ वस्तु> POST_NAME? नहीं। वह पोस्ट के स्लग को लौटा देगा, लेकिन मुझे उस एल्बम के स्लग की आवश्यकता है जो पोस्ट से जुड़ा हुआ है।
ग्रेगरी

0

Brians कोड के लिए अद्यतन, मैंने पाया कि जब ड्रॉपडाउन बॉक्स का उपयोग नहीं किया जा रहा था "डिफ़ॉल्ट" टेम्पलेट विकल्प को wp_page_template में सहेजा जा रहा था, जिसके कारण इसे डिफ़ॉल्ट नाम का टेम्पलेट ढूंढने का प्रयास करना पड़ा। यह परिवर्तन केवल विकल्प "डिफ़ॉल्ट" के लिए जाँच करता है जब पोस्ट मेटा को सहेजने और हटाने के बजाय (उपयोगी यदि आपने टेम्पलेट विकल्प को डिफ़ॉल्ट में बदल दिया है)

अन्य (MY_CUSTOM_POST_TYPE === $ _POST ['post_type']) {

यदि (esc_attr ($ _ POST ['_ wp_page_template']) === "" "":
    delete_post_meta ($ post_id, '_wp_page_template');
अन्य :
    update_post_meta ($ post_id, '_wp_page_template', esc_attr ($ _ POST ['_ wp_page_template']));
अगर अंत;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.