Hapus siput taksonomi dari permalink taksonomi hierarki kustom


21

Saya membuat taksonomi 'forum', menggunakan aturan ini:

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

Di front-end URL-nya terlihat seperti:

forums/general-discussion/sub-forum

Bagaimana saya bisa menghapus siput depan ("forum")? Yaitu, ubah URL menjadi:

general-discussion/sub-forum

Jika saya memberikan argumen slug kosong ke register_taxonomy () itu berfungsi, tapi itu menyebabkan masalah dengan permalinks dari jenis tulisan yang terkait dengan taksonomi ini


@One Trick Pony - Sudahkah Anda mencoba dan bukannya membiarkannya 'slug' => 'forums'kosong hanya dengan menghapus semuanya sekaligus 'rewrite' => array('with_front' => false, 'hierarchical' => true)? Saya pikir itu telah berhasil di masa lalu bagi saya. Pastikan juga Anda membersihkan permalinks.
eileencodes

mencobanya, dan permalinks terlihat sama. Menambahkan 'slug' => ''membuatnya berfungsi, tetapi kemudian posting menggunakan taksonomi ini menghasilkan 404
an

@One Trick Pony - Selain 'diskusi umum', segmen jalur tingkat atas apa yang Anda butuhkan?
MikeSchinkel

siapa pun %forum%harus menjadi segmen tingkat atas
onetrickpony

@One Trick Pony - Saya hanya berharap Anda memberi saya beberapa segmen jalur tingkat atas lainnya untuk konteks.
MikeSchinkel

Jawaban:


11

MEMPERBARUI

Sejak menulis inti WordPress ini telah menambahkan 'do_parse_request'pengait yang memungkinkan perutean URL ditangani secara elegan dan tanpa perlu memperpanjang WPkelas. Saya membahas topik ini secara mendalam dalam ceramah Atlanta WordCamp 2014 saya yang berjudul " Hardcore URL Routing " ; slide tersedia di tautan.

JAWABAN ASLI

Desain URL telah menjadi penting selama lebih dari satu dekade; Saya bahkan menulis blog tentang itu beberapa tahun yang lalu. Dan meskipun WordPress adalah jumlah perangkat lunak yang brilian, sayangnya sistem penulisan ulang URL-nya hanya kekurangan otak (IMHO, tentu saja. :) Bagaimanapun, senang melihat orang-orang peduli dengan desain URL!

Jawaban yang akan saya berikan adalah plugin yang saya panggil WP_Extendedyang merupakan bukti konsep untuk proposal ini pada Trac (Perhatikan bahwa proposal dimulai sebagai satu hal dan berkembang menjadi yang lain, jadi Anda harus membaca semuanya untuk melihat di mana itu menuju.)

Pada dasarnya idenya adalah untuk mensubkelas WPkelas, mengganti parse_request()metode, dan kemudian menetapkan $wpvariabel global dengan turunan dari subkelas. Kemudian di dalam diri parse_request()Anda sebenarnya memeriksa jalan demi segmen alih-alih menggunakan daftar ekspresi reguler yang harus cocok dengan URL secara keseluruhan.

Jadi untuk menyatakannya secara eksplisit, teknik ini menyisipkan logika di depan parse_request()yang memeriksa kecocokan URL-ke-RegEx dan sebagai gantinya pertama-tama mencari kecocokan istilah taksonomi, tetapi teknik ini HANYA menggantikan parse_request()dan membiarkan seluruh sisa sistem perutean URL WordPress utuh termasuk dan terutama penggunaan $query_varsvariabel.

Untuk kasus penggunaan Anda, implementasi ini hanya membandingkan segmen jalur URL dengan istilah taksonomi karena hanya itu yang Anda butuhkan. Implementasi ini memeriksa persyaratan taksonomi yang menghormati hubungan istilah orangtua-anak dan ketika menemukan kecocokan, ia menetapkan jalur URL (dikurangi garis miring utama dan garis belakang) ke $wp->query_vars['category_name'], $wp->query_vars['tag']atau $wp->query_vars['taxonomy']& & $wp->query_vars['term']serta mem-bypass parse_request()metode WPkelas.

Di sisi lain jika jalur URL tidak cocok dengan istilah dari taksonomi yang telah Anda tetapkan itu mendelegasikan logika routing URL ke sistem penulisan ulang WordPress dengan memanggil parse_request()metodeWP kelas.

Untuk menggunakan WP_Extendedcase-use Anda, Anda harus memanggil register_url_route()fungsi dari dalam functions.phpfile tema Anda seperti:

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

Apa yang ada di sini adalah kode sumber untuk plugin:

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

Meskipun untuk situs tertentu saya pikir teknik ini berfungsi dengan baik tetapi teknik ini TIDAK PERNAH digunakan untuk plugin yang akan didistribusikan di WordPress.org untuk digunakan orang lain . Jika itu adalah inti dari paket perangkat lunak berbasis WordPress maka itu mungkin tidak apa-apa. Kalau tidak, teknik ini harus dibatasi untuk meningkatkan perutean URL untuk situs tertentu .

Mengapa? Karena hanya satu plugin yang dapat menggunakan teknik ini . Jika dua plugin mencoba menggunakannya, mereka akan saling bertentangan.

Selain itu, strategi ini dapat diperluas untuk secara umum menangani hampir semua pola penggunaan yang mungkin diperlukan dan itulah yang ingin saya terapkan segera setelah saya menemukan waktu luang atau klien yang dapat mensponsori waktu yang diperlukan untuk membangun implementasi sepenuhnya generik.

CAVEAT # 2

Saya menulis ini untuk mengesampingkan parse_request()yang merupakan fungsi yang sangat besar, dan sangat mungkin bahwa saya melewatkan satu atau dua properti dari $wpobjek global yang seharusnya saya atur .. Jadi jika ada sesuatu yang tidak beres, beri tahu saya dan saya akan senang untuk riset dan revisi jawabannya jika perlu.

Bagaimanapun...


Setelah menulis ini saya menyadari bahwa saya menguji kategori bukan untuk istilah taksonomi secara umum sehingga di atas tidak akan berfungsi untuk 'forum'taksonomi namun saya akan merevisinya untuk bekerja hari ini ...
MikeSchinkel

Jadi saya telah memperbarui kode untuk mengatasi masalah yang saya sebutkan di komentar sebelumnya.
MikeSchinkel

tidak bisa mendapatkan pekerjaan ini ... apakah saya perlu mengubah aturan penulisan ulang?
onetrickpony

@One Trick Pony - Sedikit informasi diagnostik akan membantu. :) Apa yang kamu coba? Apa yang terjadi ketika Anda memasukkan URL ke browser Anda? Apakah Anda kebetulan memanggil taksonomi Anda 'forums'alih-alih 'forum'? Apakah Anda mengharapkan URL yang tertaut ke halaman ini berubah (jika ya, tidak heran, kode saya tidak membahas pencetakan URL, hanya perutean URL.)
MikeSchinkel

tidak, saya dapat mengubah URL (saya pikir ini adalah fungsi term_link yang perlu saya kaitkan untuk itu). site/rootforum/berfungsi, tetapi site/rootforum/subforum/tidak (404 kesalahan) ...
onetrickpony

7

Sederhana, sungguh.

Langkah 1: Berhenti menggunakan parameter menulis ulang sama sekali. Kami akan melempar penulisan ulang Anda sendiri.

'rewrite'=>false;

Langkah 2: Tetapkan aturan halaman verbose. Ini memaksa Halaman normal untuk memiliki aturan sendiri alih-alih menjadi catch-all di bagian bawah halaman.

Langkah 3: Buat beberapa aturan penulisan ulang untuk menangani kasus penggunaan Anda.

Langkah 4: Secara manual memaksa aturan flush terjadi. Cara termudah: pergi ke pengaturan-> permalink dan klik tombol simpan. Saya lebih suka ini daripada metode aktivasi plugin untuk penggunaan saya sendiri, karena saya dapat memaksa aturan untuk memerah setiap kali saya mengubah keadaan.

Jadi, kode waktu:

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

Ingatlah bahwa setelah menambahkan kode ini, Anda harus membuatnya aktif ketika Anda membuka aturan permalink (dengan Menyimpan halaman pada Pengaturan-> Permalinks)!

Setelah Anda menyiram aturan dan menyimpannya ke database, maka / apa pun yang harus pergi ke forum Anda = halaman taksonomi apa pun.

Aturan penulisan ulang sebenarnya tidak terlalu sulit jika Anda memahami ekspresi reguler. Saya menggunakan kode ini untuk membantu saya ketika men-debug mereka:

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

Dengan cara ini, saya bisa melihat peraturan saat ini secara sekilas di halaman saya. Ingatlah bahwa dengan diberi URL apa pun, sistem akan dimulai di bagian atas aturan dan menelusuriinya sampai menemukan yang cocok. Pencocokan ini kemudian digunakan untuk menulis ulang kueri menjadi yang lebih normal? Key = value set. Kunci-kunci itu diuraikan menjadi apa yang masuk ke objek WP_Query. Sederhana.

Sunting: Catatan tambahan, metode ini mungkin hanya akan berfungsi jika struktur posting kustom normal Anda dimulai dengan sesuatu yang bukan catchall, seperti% kategori% atau beberapa hal seperti itu. Anda harus memulainya dengan string statis atau numerik, seperti% year%. Ini untuk mencegahnya menangkap URL Anda sebelum sampai ke aturan Anda.


Jika Anda ingin lebih mudah men-debug aturan penulisan ulang Anda, saya (lagi) merekomendasikan plugin penganalisis penulisan ulang saya , yang memungkinkan Anda untuk mencoba aturan dan melihat variabel permintaan dengan cepat.
Jan Fabry

Sayangnya sistem penulisan ulang URL saat ini memaksa perataan semua pola URL potensial ke dalam daftar besar vs. mengikuti struktur pohon yang melekat pada jalur URL. Pengaturan saat ini tidak dapat dengan mudah cocok dengan array literal seperti kategori, atau nama forum ; seperti yang Anda tahu itu memaksa semua "Halaman" URL untuk dievaluasi terlebih dahulu. Pencocokan berdasarkan segmen jalur dan pencocokan dalam berbagai cara (array literal, kategori, tag, ketentuan pajak, nama pengguna, tipe posting, nama posting, callback, kait filter, dan akhirnya RegEx) akan meningkatkan kompleksitas dengan lebih baik, dan akan lebih mudah untuk mengerti.
MikeSchinkel

Mike: Sebenarnya, itu tidak mudah untuk dipahami sama sekali, karena saya belum mendapatkan petunjuk pertama WTF yang sedang Anda bicarakan di sana. Gagasan perutean URL Anda membingungkan dan sulit, dan seperti yang mungkin Anda ketahui, saya tidak setuju dengan mereka. Pencarian datar lebih masuk akal dan lebih fleksibel daripada Anda cenderung memberikannya penghargaan. Kebanyakan orang tidak menginginkan semua kompleksitas yang tidak perlu dalam URL mereka, dan hampir tidak ada yang membutuhkannya juga.
Otto

Terima kasih, tapi saya pikir saya sudah mencoba ini sebelumnya ( wordpress.stackexchange.com/questions/9455/… )
onetrickpony

Untungnya WordPress Jawaban sekarang memungkinkan orang-orang yang melakukan kontrol menginginkan URL mereka untuk akhirnya memiliki suara, dan mereka tampaknya ada banyak (100 +). Tetapi saya menghormati bahwa Anda mungkin tidak dapat mengikuti contoh saya sebelum implementasi penuh. Saya memperkirakan, begitu pendekatan yang saya anjurkan sepenuhnya diimplementasikan dalam sebuah plugin dan setelah sekitar 6-12 bulan itu akan menjadi cara yang disukai untuk situs CMS berbasis WordPress untuk merutekan URL mereka. Jadi mari kita lanjutkan debat ini dalam waktu sekitar 9 bulan.
MikeSchinkel

4

Anda tidak akan dapat melakukan ini menggunakan WP_Rewrite saja, karena itu tidak dapat membedakan antara siput istilah dan siput posting.

Anda juga harus terhubung ke 'permintaan' dan mencegah 404, dengan mengatur var permintaan posting alih-alih yang taksonomi.

Sesuatu seperti ini:

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

Perhatikan bahwa taksonomi harus didefinisikan sebelumnya jenis posting.

Ini akan menjadi saat yang tepat untuk menunjukkan bahwa memiliki taksonomi dan jenis posting dengan kueri var yang sama adalah Ide Buruk.

Juga, Anda tidak akan dapat menjangkau posting yang memiliki siput yang sama dengan salah satu syarat.


Setuju bahwa memiliki taksonomi dan tipe posting dengan kueri var yang sama adalah Ide Buruk, tetapi itu mungkin menyiratkan orang yang memiliki taksonomi dan tipe posting dengan nama yang sama adalah ide yang buruk, yang tidak demikian. Jika menggunakan nama yang sama maka hanya satu dari dua yang harus memiliki var permintaan.
MikeSchinkel

2

Saya akan melihat kode plugin kucing tingkat atas:

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

Anda dapat dengan mudah beradaptasi sehingga mencari siput taksonomi kustom Anda dengan mengubah

$category_base = get_option('category_base');

on line 74 ke sesuatu seperti:

$category_base = 'forums';

Mungkin berfungsi untuk kategori, tetapi tidak untuk taksonomi khusus (setidaknya dalam wp 3.1) ... Saya berhasil mengubah URL, tapi saya mendapatkan 404 kesalahan
onetrickpony

2

Saya sarankan untuk melihat plugin Custom Post Permalinks . Saya tidak punya waktu untuk menguji sekarang, tetapi mungkin membantu dengan situasi Anda.


tidak, itu hanya menangani posting, bukan taksonomi, dan bahkan jika itu akan, saya harus menambahkan semacam awalan sebelumnya %forum%, yang persis apa yang saya coba hindari ...
onetrickpony

2

Karena saya terbiasa dengan pertanyaan Anda yang lain , saya akan menjawab dengan itu dalam pikiran.

Saya belum menguji ini sama sekali, tetapi mungkin berhasil jika Anda menjalankan ini sekali setelah Anda mendaftarkan semua permastructs yang Anda inginkan .:

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

Kegunaannya: menghapus aturan penulisan ulang yang dihasilkan dari topik permalink dari aliran normal array aturan dan menggabungkannya kembali di akhir array. Ini mencegah aturan-aturan itu mengganggu aturan penulisan ulang lainnya. Selanjutnya, itu memaksa aturan penulisan ulang verbose (setiap halaman mendapatkan aturan individu dengan ekspresi reguler tertentu). Ini mencegah halaman dari mengganggu aturan topik Anda. Akhirnya, ia mengeksekusi hard flush (pastikan file .htaccess Anda dapat ditulisi, jika tidak ini tidak akan berfungsi) dan menyimpan berbagai aturan penulisan ulang yang sangat rumit.


mencobanya, tidak ada yang berubah
onetrickpony



2

Gunakan garis miring sebagai nilai untuk slug ... 100% berfungsi

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

2
tidak cukup, ini menyebabkan semua pagejenis posting ke 404.
Milo
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.