Taksonomi sümüklü böceklerini özel bir hiyerarşik taksonomi permalinkinden çıkarın


21

Bu kuralları kullanarak bir 'forum' taksonomisi oluşturdum:

register_taxonomy(
  'forum',
  array('topic'),
  array(
    'public' => true,
    'name' => _a('Forums'),
    'singular_name' => _a('Forum'),
    'show_ui' => true,
    'show_in_nav_menus' => true,
    'hierarchical' => true,

    'labels' => array(
      'name' => _a('Forums'),
      'singular_name' => _a('Forum'),
      'search_items' => _a('Search Forums'),
      'popular_items' => _a('Popular Forums'),
      'all_items' => _a('All Forums'),
      'parent_item' => _a('Parent Forum'),
      'parent_item_colon' => _a('Parent Forum:'),
      'edit_item' => _a('Edit Forum'),
      'update_item' => _a('Update Forum'),
      'add_new_item' => _a('Add New Forum'),
      'new_item_name' => _a('New Forum Name'),
    ),
    'query_var' => true,
    'rewrite' => array('slug' => 'forums', 'with_front' => false, 'hierarchical' => true),  
  )
);

Ön uçta URL'ler şuna benzer:

forums/general-discussion/sub-forum

Ön grubu ("forumlar") nasıl çıkarabilirim? Yani, URL’leri şu şekilde değiştirin:

general-discussion/sub-forum

Register_taxonomy () işlevine boş bir sümüklügü argümanını iletersem çalışır, ancak bu taksonomi ile ilişkili posta tipinin kalıcı bağlantılarıyla ilgili sorunlara neden olur.


@One Trick Pony - 'slug' => 'forums'Sadece tamamen kaldırmak ve sadece sahip olmakla boş bırakmak yerine denediniz 'rewrite' => array('with_front' => false, 'hierarchical' => true)mi? Sanırım bu geçmişte benim için işe yaradı. Ayrıca kalıcı bağlantıları temizlediğinizden emin olun.
eileen kodları

Bunu denedim ve permalink'ler aynı görünüyor. Ekleme 'slug' => ''çalışmasını sağlar, ancak daha sonra bu taksonomiyi kullanan gönderiler
404'ler

@ Bir Trick Pony - 'Genel tartışma' dışında başka hangi üst düzey yol bölümlerine ihtiyacınız var?
MikeSchinkel

Herhangi %forum%bir üst seviye segment olmalı
onetrickpony

@ Bir Trick Pony - Sadece bağlam için bana başka üst düzey yol segmentleri vermeyi umuyordum.
MikeSchinkel

Yanıtlar:


11

GÜNCELLEŞTİRME

Bu WordPress çekirdeğini yazdığından beri 'do_parse_request', URL yönlendirmesinin zarif bir şekilde ve WPsınıfı genişletmeye gerek kalmadan ele alınmasına olanak sağlayan kanca eklendi . 2014 Atlanta WordCamp konuşmamda " Hardcore URL Routing " ; slaytlar bağlantıda bulunmaktadır.

ORİJİNAL CEVAP

URL Tasarımı , on yıldan uzun bir süredir olması önemliydi; Birkaç yıl önce bir blog bile yazdım . Ve WordPress toplam olsa da, yazılımın mükemmel bir parçası ne yazık ki , URL yeniden yazma sistemi sadece beyin ölümü eksik (IMHO, elbette. :) Yine de, URL tasarımını önemseyen insanları görmekten memnun oldum !

Vereceğim cevap , Trac'teki bu teklifWP_Extended için bir konsept kanıtı olarak adlandırdığım bir eklentidir (Teklifin bir şey olarak başladığını ve başka bir evrime dönüştüğünü unutmayın, bu yüzden nerede olduğunu görmek için her şeyi okumanız gerekir. yöneldi.)

Temel olarak fikir sınıfı alt WPsınıfa koymak , parse_request()yöntemi geçersiz kılmak ve genel $wpdeğişkeni alt sınıfın bir örneğiyle atamaktır . Sonra içinde parse_request(), aslında URL’yle tam olarak eşleşmesi gereken normal ifadelerin listesini kullanmak yerine yolu yol bölümünden inceleyin .

Açıkça belirtmek gerekirse, bu teknik parse_request()URL-to-RegEx eşleşmelerini kontrol edenin önüne mantık ekler ve bunun yerine ilk olarak taksonomi terim eşleşmelerini arar, ancak SADECEparse_request() WordPress URL yönlendirme sisteminin geri kalanının tamamını değiştirir ve bırakır. özellikle $query_varsdeğişken kullanımı .

Kullanım durumunuz için bu uygulama yalnızca URL yolu segmentlerini taksonomi terimleriyle karşılaştırır, çünkü ihtiyacınız olan tek şey budur. Bu uygulama, ebeveyn-çocuk ilişkileri terimi saygı sınıflandırma koşullar denetler ve bir eşleşme bulduğunda bu URL yolu atar (ön ve arka eğik çizgi eksi) için $wp->query_vars['category_name'], $wp->query_vars['tag']ya da $wp->query_vars['taxonomy']ve $wp->query_vars['term']ve atlar parse_request()yöntemi WPsınıfı.

Öte yandan, URL yolu belirttiğiniz bir taksonomiden bir terim ile eşleşmiyorsaparse_request() , WPsınıf yöntemini çağırarak URL yönlendirme mantığını WordPress yeniden yazma sistemine devreder .

Kullanım WP_Extendeddurumunuz için kullanmak üzere register_url_route()işlevi temanızın functions.phpdosyasından şöyle çağırmanız gerekir :

add_action('init','init_forum_url_route');
function init_forum_url_route() {
  register_url_route(array('taxonomy'=>'forum'));
}

Eklentinin kaynak kodu burada:

<?php
/*
Filename: wp-extended.php
Plugin Name: WP Extended for Taxonomy URL Routes
Author: Mike Schinkel
*/
function register_url_route($args=array()) {
  if (isset($args['taxonomy']))
    WP_Extended::register_taxonomy_url($args['taxonomy']);
}
class WP_Extended extends WP {
  static $taxonomies = array();
  static function on_load() {
    add_action('setup_theme',array(__CLASS__,'setup_theme'));
  }
  static function register_taxonomy_url($taxonomy) {
    self::$taxonomies[$taxonomy] = get_taxonomy($taxonomy);
  }
  static function setup_theme() { // Setup theme is 1st code run after WP is created.
    global $wp;
    $wp = new WP_Extended();  // Replace the global $wp
  }
  function parse_request($extra_query_vars = '') {
    $path = $_SERVER['REQUEST_URI'];
    $domain = str_replace('.','\.',$_SERVER['SERVER_NAME']);
    //$root_path = preg_replace("#^https?://{$domain}(/.*)$#",'$1',WP_SITEURL);
$root_path = $_SERVER['HTTP_HOST'];

    if (substr($path,0,strlen($root_path))==$root_path)
      $path = substr($path,strlen($root_path));
    list($path) = explode('?',$path);
    $path_segments = explode('/',trim($path,'/'));
    $taxonomy_term = array();
    $parent_id = 0;
    foreach(self::$taxonomies as $taxonomy_slug => $taxonomy) {
      $terms = get_terms($taxonomy_slug);
      foreach($path_segments as $segment_index => $path_segment) {
        foreach($terms as $term_index => $term) {
          if ($term->slug==$path_segments[$segment_index]) {
            if ($term->parent!=$parent_id) { // Make sure we test parents
              $taxonomy_term = array();
            } else {
              $parent_id = $term->term_id; // Capture parent ID for verification
              $taxonomy_term[] = $term->slug; // Collect slug as path segment
              unset($terms[$term_index]); // No need to scan it again
            }
            break;
          }
        }
      }
      if (count($taxonomy_term))
        break;
    }
    if (count($taxonomy_term)) {
      $path = implode('/',$taxonomy_term);
      switch ($taxonomy_slug) {
        case 'category':
          $this->query_vars['category_name'] = $path;
          break;
        case 'post_tag':
          $this->query_vars['tag'] = $path;
          break;
        default:
          $this->query_vars['taxonomy'] = $taxonomy_slug;
          $this->query_vars['term'] = $path;
          break;
      }
    } else {
      parent::parse_request($extra_query_vars); // Delegate to WP class
    }
  }
}
WP_Extended::on_load();

PS CAVEAT # 1

Her ne kadar belirli bir site için bu tekniğin mükemmel bir şekilde çalıştığını düşünüyorum, ancak bu tekniğin başkalarının kullanması için WordPress.org'da dağıtılması için bir eklenti ASLA kullanılmamalıdır . WordPress tabanlı bir yazılım paketinin çekirdeğinde ise, o zaman sorun olabilir. Aksi halde, bu teknik, belirli bir sitenin URL yönlendirmesini iyileştirmeyle sınırlı olmalıdır .

Niye ya? Çünkü bu tekniği yalnızca bir eklenti kullanabilir . İki eklenti kullanmaya çalışırsa birbirleriyle çatışırlar.

Bir yana, bu strateji, pratik olarak gerekli olabilecek her kullanım durumu modelini pratik olarak ele alacak şekilde genişletilebilir. tamamen genel uygulamalar oluşturmak.

CAVEAT # 2

Bunu parse_request(), çok büyük bir işlev olan geçersiz kılmak için yazdım ve ayarlamam gereken bir özelliği ya da iki küresel $wpnesneyi kaçırmam oldukça muhtemeldir . araştırın ve gerekirse cevabı gözden geçirin.

Neyse ...


Bunu yazdıktan sonra, genel olarak taksonomi terimleri yerine kategoriler için test ettiğimi fark ettim, böylece yukarıdakiler 'forum'taksonomi için işe yaramayacak ancak bugün daha sonra çalışmak üzere revize
edeceğim

Bu yüzden önceki yorumda bahsettiğim sorunu gidermek için kodu güncelledim.
MikeSchinkel

bu işi alamıyorum ... yeniden yazma kurallarını değiştirmem gerekiyor mu?
onetrickpony

@One Trick Pony - Biraz daha tanılayıcı bilgi yardımcı olacaktır. :) Ne denedin? URL’leri tarayıcınıza girdiğinizde ne olur? Şans eseri 'forums'yerine taksonominizi 'forum'mi çağırdınız ? Bu sayfalara bağlantı veren URL’lerin değişmesini mi bekliyorsunuz (evetse, merak etmiyorsanız, kodum URL’lerin yazdırılmasını değil, yalnızca URL’lerin yönlendirilmesini de sağlar.)
MikeSchinkel

hayır, URL’leri değiştirebilirim (bunun için bağlanması gereken term_link işlevi olduğunu düşünüyorum). site/rootforum/çalışıyor, ama site/rootforum/subforum/yok (404 hata) ...
onetrickpony

7

Gerçekten basit.

Adım 1: Yeniden yazma parametresini hiç kullanmayı bırak. Kendi yazılarını yazacağız.

'rewrite'=>false;

Adım 2: Ayrıntılı sayfa kurallarını ayarlayın. Bu, normal Sayfaları sayfanın alt kısmında bir yakalayıcı olmak yerine kendi kurallarına sahip olmaya zorlar.

Adım 3: Kullanım durumlarınızı ele almak için yeniden yazma kuralları oluşturun.

Adım 4: El ile bir yıkama kurallarını el ile zorla. En kolay yol: ayarlar-> kalıcı bağlantıya gidin ve kaydet düğmesine tıklayın. Bunları kendi kullanımım için bir eklenti etkinleştirme yöntemine tercih ederim, çünkü her şeyi değiştirdiğimde kuralları yıkamak için zorlayabilirim.

Yani, kod zamanı:

function test_init() {
    // create a new taxonomy
    register_taxonomy(
        'forum',
        'post',
        array(
            'query_var' => true,
            'public'=>true,
            'label'=>'Forum',
            'rewrite' => false,
        )
    );

    // force verbose rules.. this makes every Page have its own rule instead of being a 
    // catch-all, which we're going to use for the forum taxo instead
    global $wp_rewrite;
    $wp_rewrite->use_verbose_page_rules = true;

    // two rules to handle feeds
    add_rewrite_rule('(.+)/feed/(feed|rdf|rss|rss2|atom)/?$','index.php?forum=$matches[1]&feed=$matches[2]');
    add_rewrite_rule('(.+)/(feed|rdf|rss|rss2|atom)/?$','index.php?forum=$matches[1]&feed=$matches[2]');

    // one rule to handle paging of posts in the taxo
    add_rewrite_rule('(.+)/page/?([0-9]{1,})/?$','index.php?forum=$matches[1]&paged=$matches[2]');

    // one rule to show the forum taxo normally
    add_rewrite_rule('(.+)/?$', 'index.php?forum=$matches[1]');
}

add_action( 'init', 'test_init' );

Unutmayın, bu kodu ekledikten sonra, kalıcı bağlantı kurallarını temizlediğinizde aktif hale getirmeniz gerektiğini unutmayın (Sayfayı Ayarlar-> Permalinks'e kaydederek)!

Kuralları temizledikten ve veri tabanına kaydettikten sonra, / forumunuza gitmek için ne gerekiyorsa = hangi taksonomi sayfasına giderseniz.

Düzenli ifadeleri anlıyorsanız, yeniden yazma kuralları gerçekten zor değil. Hata ayıklama sırasında bana yardım etmek için bu kodu kullanıyorum:

function test_foot() {
    global $wp_rewrite;
    echo '<pre>';
    var_dump($wp_rewrite->rules);
    echo '</pre>';
}
add_action('wp_footer','test_foot');

Bu şekilde, geçerli kuralları sayfamda bir bakışta görebilirim. Unutmayın ki, herhangi bir URL verildiğinde, sistem kuralların en üstünde başlar ve eşleşen bir tane bulana kadar onlar arasından geçer. Eşleşme daha sonra sorguyu daha normal görünümlü bir? Anahtar = değer kümesine yeniden yazmak için kullanılır. Bu anahtarlar WP_Query nesnesine girenlere ayrıştırılır. Basit.

Düzenleme: Yan not, bu yöntem yalnızca normal özel gönderi yapınız,% kategori% gibi bir şey veya benzeri bir şeyle başlamazsa işe yarayacaktır. Statik bir dize veya% year% gibi bir sayısal sayı ile başlatmanız gerekir. Bu, kurallarınızı almadan önce URL’nizi yakalamasını önlemek içindir.


Eğer yeniden yazma kurallarınızda daha kolay hata ayıklama yapmak istiyorsanız, ben (tekrar) yeniden yazma analizci eklentisini öneririm ; bu, kuralları denemenizi ve anında sorgu değişkenlerini görmenizi sağlar.
Jan Fabry

Ne yazık ki mevcut URL yeniden yazma sistemi, URL yollarının doğal ağaç yapısını izleyerek tüm potansiyel URL modellerinin düzleştirilmesini büyük bir listeye zorlar. Geçerli kurulum, kategoriler veya forum adları gibi bir dizi hazır bilgi dizisiyle uygun şekilde eşleşemez ; Bildiğiniz gibi, önce tüm "Sayfa" URL'lerini değerlendirmeye zorlar . Yol segmentine göre eşleştirme ve birden çok yolla eşleştirme (değişmezler, kategoriler, etiketler, vergi terimleri, kullanıcı adları, posta tipleri, posta adları, geri aramalar, filtre kancaları ve son olarak RegEx dizisi) karmaşıklık için daha iyi ölçeklenir ve daha kolay olur anlamak.
MikeSchinkel

Mike: Aslında, bunu anlamak hiç de kolay değil, çünkü orada bahsettiğiniz ilk WTF ipucunu almadım. URL yönlendirme fikirleriniz kafa karıştırıcı ve zordur ve muhtemelen bildiğiniz gibi ben onlara katılmıyorum. Düz arama daha mantıklı ve sizin için kredi verme eğiliminde olduğundan daha esnek. Çoğu insan URL'lerinde bu kadar karmaşıklık istemiyor ve neredeyse hiç kimsenin de buna ihtiyacı yok.
Otto,

Teşekkürler, ama sanırım bunu daha önce denedim ( wordpress.stackexchange.com/questions/9455/… )
onetrickpony

Neyse WordPress şimdi Cevapları verir insanlar yapmak onların URL'lerin Talep kontrolünü nihayet söz sahibi ve onlar birçok olmaya (100 +) görünmektedir. Ancak tam bir uygulamadan önce örneğimi izleyemeyeceğinize saygı duyuyorum. Savunduğum yaklaşım tamamen bir eklentide uygulandığında ve yaklaşık 6-12 ay sonra WordPress tabanlı CMS sitelerinin URL'lerini yönlendirmeleri için tercih edilen bir yol haline geleceğini tahmin ediyorum. Bu tartışma yaklaşık 9 ay içinde devam edelim.
MikeSchinkel

4

Bunu yalnızca WP_Rewrite kullanarak yapamazsınız, çünkü sümüklü böcek ve sümüklü böcek terimlerini ayırt edemez.

Ayrıca, "istek" e bağlanmalı ve 404'ü engellemelisiniz, sorgulama taksonomisi yerine var sorgusunu değiştirerek.

Bunun gibi bir şey:

function fix_post_request( $request ) {
    $tax_qv = 'forum';
    $cpt_name = 'post';

    if ( !empty( $request[ $tax_qv ] ) ) {
        $slug = basename( $request[ $tax_qv ] );

        // if this would generate a 404
        if ( !get_term_by( 'slug', $slug, $tax_qv ) ) {
            // set the correct query vars
            $request[ 'name' ] = $slug;
            $request[ 'post_type' ] = $cpt_name;
            unset( $request[$tax_qv] );
        }
    }

    return $request;
}
add_filter( 'request', 'fix_post_request' );

Taksonominin posta tipinden önce tanımlanması gerektiğini unutmayın .

Taksonomiye ve aynı sorgu değişkenine sahip bir yazı tipine sahip olmanın Kötü Bir Fikir olduğunu belirtmek için iyi bir zaman olurdu.

Ayrıca, şartlardan biriyle aynı sıkıntıya sahip olan yayınlara ulaşamazsınız.


Bir taksonomiye ve aynı sorguya sahip bir yazı tipine sahip olmanın kötü bir fikir olduğunu kabul etti, ancak bu durum aynı taksonomiye sahip olan ve aynı ada sahip bir yazı tipine sahip olabilecek anlamına gelebilir . Aynı adı kullanıyorsanız, ikisinden yalnızca birinin var sorgusu olmalıdır.
MikeSchinkel

2

Üst düzey kedi eklentisinin koduna bir göz atardım:

http://fortes.com/projects/wordpress/top-level-cats/

Kolayca adapte olabilir, bu yüzden değiştirerek özel taksonomi sümüklü böcek arıyor

$category_base = get_option('category_base');

on line 74 gibi bir şey için:

$category_base = 'forums';

Kategoriler için çalışabilir, ancak özel taksonomiler için geçerli değil (en azından wp 3.1'de) ... URL'leri değiştirmeyi başardım, ancak 404 hata
alıyorum

2

Custom Post Permalinks eklentisine göz atmanızı öneririm . Şu an test etmek için zamanım yok, ancak durumunuza yardımcı olabilir.


öyle değil, sadece yayınları kullanıyor, taksonomileri değil, ve olsa bile, daha önce bir tür önek eklemek zorunda kaldım %forum%, bu tam olarak kaçınmaya çalıştığım şey ...
onetrickpony

2

Diğer sorunuza aşina olduğum için , buna cevap vereceğim.

Bunu hiç test etmedim, ancak istediğiniz tüm permas yapıları kaydettikten hemen sonra bir kez uygularsanız, işe yarayabilir:

class RRSwitcher {
  var $rules;
  function RRSwitcher(){
    add_filter( 'topic_rewrite_rules', array( $this, 'topics' ) );
    add_filter( 'rewrite_rules_array', array( $this, 'rules' ) );
  }
  function topics( $array ){
    $this->rules = $array;
    return array();
  }
  function rules( $array ){
    return array_merge( (array)$array, (array)$this->rules );
  }
}
$RRSwitcher = new RRSwitcher();
global $wp_rewrite;
$wp_rewrite->use_verbose_rules = true;
$wp_rewrite->flush_rules();

Bu ne yapar: kurallar dizisinin normal akışından konular permalink'ten oluşturulan yeniden yazma kurallarını kaldırır ve dizinin sonunda yeniden birleştirir. Bu, bu kuralların başka bir yeniden yazma kuralına müdahale etmesini önler. Daha sonra ayrıntılı yeniden yazma kurallarını zorlar (her sayfa belirli bir düzenli ifadeye sahip bireysel bir kural alır). Bu, sayfaların konunuzun kurallarına müdahale etmesini önler. Son olarak, sert bir floş gerçekleştirir (.htaccess dosyanızın yazılabilir olduğundan emin olun, aksi takdirde bu işe yaramaz) ve çok büyük, çok karmaşık çok yeniden yazma kuralları dizisini kaydeder.


denedim, hiçbir şey değişmedi
onetrickpony



2

Bir kullan çizgi değeri olarak sülük ... 100% çalışma

'rewrite' => array(
    'slug'       => '/', 
    'with_front' => FALSE
 ),

2
tam olarak bu, tüm pageyazı tipinin 404 olmasına neden olur .
Milo
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.