single - özel yayın türleri için {$ post_type} - {slug} .php


20

Wordpress şablon hiyerarşisinin en sevdiğim kısmı, bir şablon seçmek için Wordpress'te sayfayı düzenlemek zorunda kalmadan, sayfalar için şablon dosyalarını hızlıca oluşturabilmektir.

Şu anda bunu yapabiliriz:

sayfası- {sümüklüböcek} php

Ama bunu yapabilmek istiyorum:

tek {post_type} - {sümüklüböcek} php

Böylece, örneğin, adlı bir yazı türünde review, "Benim Büyük İnceleme" adlı bir yazı için bir şablon yapabilirsingle-review-my-great-review.php

Bunu daha önce ayarlayan var mı? single-{post_type}-{slug}.php


Daha önce hiç böyle bir kurulum kullanmadınız, ancak çok karmaşıksa, neden sadece bir şablon dosyası yapmıyorsunuz ve söz konusu incelemeyle ilişkilendirmiyorsunuz.
Shane

WP 3.4 otomatik olarak alınır single-{post_type}-{slug}.php, bu nedenle WP 3.4'e yükseltme başka bir seçenektir.
yitwail

Yanıtlar:


19

A) Çekirdek

Kodeks Şablonu Hiyerarşi açıklamasında görebileceğiniz gibi single-{$post_type}.php, zaten desteklenmektedir.


B) Çekirdek Hiyerarşiyi Genişletmek

Şimdi içeride bazı filtreler ve kancalar var /wp-includes/template-loader.php.

  • do_action('template_redirect');
  • apply_filters( 'template_include', $template )
  • AND: içindeki belirli bir filtre get_query_template( $type, ... ):"$type}_template"

B.1) Nasıl çalışır?

  1. Şablon yükleyici dosyasının içinde şablon var / wp_query koşullu: sorgusu tarafından yüklenir is_*().
  2. Koşullu daha sonra tetiklenir ("tek" şablonda): is_single() && $template = get_single_template()
  3. Bu daha sonra tetikler get_query_template( $type, $templates )nerede, $typeolduğusingle
  4. Sonra "{$type}_template"filtre var

C) Çözüm

Biz gibi sadece alır bir şablonla hiyerarşi uzatmak istiyorum önce yüklenen fiili "single-{$object->post_type}.php"şablona biz hiyerarşiyi yolunu kesmek ve şablonlar dizinin başlangıcına yeni bir şablon ekleyeceğiz.

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

NOT: (Varsayılan nesneler bilgi kutusundan başka bir şey kullanmak istiyorsanız) Kalıcı bağlantı yapınıza $sluggöre ayar yapmanız gerekir . Globalden ihtiyacınız olan her şeyi kullanın (object) $post.

Trac Biletleri

Yukarıdaki yaklaşım şu anda olduğu gibi değil desteklenen, burada trac biletlerin bir listesi (yalnızca mutlak bulunduğu yolu bu şekilde filtre edebilirsiniz):


Bunu test etmek istiyorum, ancak sonunda add_filter satırınızda eksik bir şey var gibi görünüyor.
supertrue

@supertrue İyi yakaladım. :) )Filtrenin içinde başka bir eksik daha bulundu . Sabit. Belki çizgiyi şablonun içindeki sümükten önce bir alt çizgi ile değiştirmek istersiniz. Sadece son ekin şablonlara bakarken daha iyi görünmesine izin vermek için.
kaiser

Site genelinde bu hataya neden oluyor: Uyarı: array_unshift () [function.array-unshift]: İlk argüman [array_unshift içeren satırda] bir dizi olmalıdır
supertrue

Tamam, ama sonra başka bir şey çekirdek şablonları ele geçiriyor. İşlev iyi çalışıyor ve $templatesbir dizidir. Bu macunundaki temel işlevlere bakın (son kullanma tarihi yoktur). Eğer bir yükleme ile bunu test emin olun olmadan eklentileri ve varsayılan tema. Ardından birbiri ardına etkinleştirin ve hatanın hala devam edip etmediğine bakın.
kaiser

Evet, hata ayıkladım ve ilk bulunan şablonun son mutlak yolunu tekrar dize olarak alıyorum. Cevabı değiştirmeden önce bazı temel geliştiricilerle bunun hakkında konuşmam gerekecek. Ayrıca: Bir şeyi karıştırdım: slugsadece terimler ve taksonomiler için kullanılabilir. $post->post_nameKalıcı bağlantı yapınıza uyan ile değiştirmelisiniz . Şu anda, perma yapınıza ve yeniden yazma kurallarınıza bağlı olarak yolu almak ve değiştirmekle tüm durumlar için bunu otomatik olarak yapmanın bir yolu yoktur. Başka bir güncelleme bekliyoruz.
kaiser

4

Şablon Hiyerarşi görüntüsünün ardından böyle bir seçenek göremiyorum.

Yani heres nasıl bu konuda gitmek istiyorum:

Çözüm 1 (Bence en iyisi)

Bir şablon dosyası oluşturun ve incelemeyle ilişkilendirin

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

Şablon php dosyasını tema dizininize eklediğinizde, yayınınızın düzenleme sayfasında şablon seçeneği olarak görünür.

Çözüm 2

Bu muhtemelen template_redirectkanca kullanılarak gerçekleştirilebilir .

Function.php dosyasında:

 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' );

DÜZENLE

Eklenen file_existsçek


Neden exit;oradasın?
kaiser

@kaiser O sırada takip ettiğim herhangi bir öğreticide olmalı, eğer gerekli değilse kaldıracağım.
Shane

1
@kaiser: exit()Varsayılan şablonun yüklenmesini önlemek için gereklidir.
scribu

Çözüm 1, yayınlar için değil, yalnızca sayfalar için çalışır.
IXN

2

Üst yanıt (4 yıl öncesinden) artık çalışmıyor, ancak WordPress kodeksinin çözümü burada :

<?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

Sayfa Şablonlarını Kullan

Ölçeklenebilirlik için başka bir yaklaşım page, özel yazı türünüz için yazı türündeki sayfa şablonu açılır işlevini çoğaltmak olacaktır .

Yeniden Kullanılabilir Kod

Kodda çoğaltma iyi bir uygulama değildir. Fazla mesai bir kod tabanına ciddi bir şişkinliğe neden olabilir, o zaman bir geliştiricinin yönetmesini çok zorlaştırır. Her bir bilgi için bir şablon oluşturmak yerine, büyük olasılıkla bire bir post-to-template yerine tekrar kullanılabilecek bire-çok şablona ihtiyacınız olacaktır.

Kod

# 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');

Bu biraz geç bir cevap, ancak web'de hiç kimse bu yaklaşımı anlayabildiğim kadar belgelemediğinden değerli olacağını düşündüm. Umarım bu birisine yardım eder.


1

Benim durumumda, bir Albüm sınıflandırmasına bağlı Albüm ve Parça özel yayın türlerim var. Albüm sınıflandırmasına bağlı olarak Albüm ve Parça yayınları için farklı Tek şablonlar kullanmak istedim.

Yukarıdaki Kaiser cevabına dayanarak bu kodu yazdım. İyi çalışıyor.
Not. Add_action () gerek yoktu.

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

Artık single-gregory-cpt-track-tax-serendipity.php adlı şablonları oluşturabilirim ve single-gregory-cpt-album-tax-serendipity.php ve WP bunları otomatik olarak kullanacak; 'vergi-serendipity', ilk Albüm sınıflandırma terimi için bilgi kaynağıdır.

referans için, 'single_template' filtre kancası şu şekilde bildirilmiştir:
/wp-includes/theme.php:get_query_template()

Örnek kod için teşekkür ederim Kaiser.

Şerefe, Gregory


Merhaba Greg - WPSE'ye hoş geldiniz. Lütfen cevapları yalnızca soruların cevapları olarak gönderin - takip sorularını değil. Mevcut bir cevap tarafından cevaplanmayan ve yorum için çok büyük bir sorunuz varsa, lütfen başka bir soru açın :)
Stephen Harris

1
dize / dizi sorusu kaldırıldı :-)
Gregory

1
"Örnek kod için teşekkür ederim Kaiser." - Rica ederim.
kaiser

senin için çalışıyor mu her şeyden önce, '$ template' kodunuzda yorumlanmamalıdır .. ve sanırım '$ album_tax [0] -> slug' yerine '$ object-> post_name' olmalı, değil mi?
gregmatys

$ şablon satırı düzeltildi. teşekkür ederim. $ object-> POST_NAME? Hayır. bu yazı slug döndürür, ama ben yazı bağlı olduğu albüm slug gerekir.
Gregory

0

Brians kodu için güncelleme, açılan kutu kullanılmadığında "varsayılan" şablon seçeneğinin varsayılan denilen bir şablon bulmaya çalışmasına neden olan wp_page_template içine kaydedildiğini buldum. bu değişiklik yalnızca kaydederken "varsayılan" seçeneğini denetler ve bunun yerine meta meta'yı siler (şablon seçeneğini varsayılana değiştirdiyseniz yararlıdır)

elseif (MY_CUSTOM_POST_TYPE === $ _POST ['post_type']) {

if (esc_attr ($ _ POST ['_ wp_page_template']) === "varsayılan"):
    delete_post_meta ($ post_id, '_wp_page_template');
Başka :
    update_post_meta ($ post_id, '_wp_page_template', esc_attr ($ _ POST ['_ wp_page_template']));
endif;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.