Entfernen Sie den Taxonomie-Slug aus einem benutzerdefinierten hierarchischen Taxonomie-Permalink

Ich habe eine “Forum” -Taxonomie erstellt, die folgende Regeln verwendet:

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

Im Frontend sieht die URL folgendermaßen aus:

 forums/general-discussion/sub-forum 

Wie kann ich die Front Slug (“Foren”) entfernen? Dh, ändern Sie die URLs zu:

 general-discussion/sub-forum 

Wenn ich ein leeres slug-Argument an register_taxonomy () übergebe, funktioniert es, aber das verursacht Probleme mit den Permalinks des Post-Typs, der dieser Taxonomie zugeordnet ist

Solutions Collecting From Web of "Entfernen Sie den Taxonomie-Slug aus einem benutzerdefinierten hierarchischen Taxonomie-Permalink"

AKTUALISIEREN

Seit dem Schreiben dieses WordPress-cores wurde der 'do_parse_request' Hook hinzugefügt, mit dem URL-Routing elegant gehandhabt werden kann, ohne dass die WP class erweitert werden muss. Ich habe das Thema ausführlich in meinem Atlanta WordCamp Talk mit dem Titel Hardcore URL Routing ” behandelt ; Die Folien sind unter dem Link verfügbar.

ORIGINAL ANTWORT

URL-Design ist seit mehr als einem Jahrzehnt wichtig; Ich habe sogar vor Jahren ein Blog darüber geschrieben . Und während WordPress ist eine brillante Software ist es leider URL Rewrite-System ist nur kurz vor hirntot (IMHO, natürlich. 🙂 Wie auch immer, froh zu sehen, die Menschen kümmern sich um URL-Design!

Die Antwort, die ich liefern werde, ist ein Plugin, das ich WP_Extended , das ist ein Konzeptnachweis für diesen Vorschlag auf Trac (Beachten Sie, dass der Vorschlag als eine Sache begann und sich in eine andere WP_Extended , so dass Sie die ganze Sache lesen müssen, um zu sehen wohin es ging.)

Grundsätzlich besteht die Idee darin, die WP class zu unterklassen, die parse_request() -Methode zu überschreiben und dann die globale $wp Variable einer Instanz der Unterklasse zuzuordnen. Dann untersuchen Sie innerhalb von parse_request() das Pfad- für-Pfad-Segment, anstatt eine Liste von regulären Ausdrücken zu verwenden, die mit der URL in ihrer Gesamtheit übereinstimmen müssen.

parse_request() es explizit parse_request() , fügt diese Technik eine Logik vor der parse_request() die nach Übereinstimmungen mit URL-zu-RegEx sucht und stattdessen nach Übereinstimmungen mit Taxonomie-Begriffen sucht, aber sie ersetzt nur parse_request() und hinterlässt den gesamten Rest von WordPress URL-Routing-System intakt einschließlich und vor allem die Verwendung der Variablen $query_vars .

Für Ihren Anwendungsfall vergleicht diese Implementierung nur URL-Pfadsegmente mit Taxonomiebegriffen, da dies alles ist, was Sie brauchen. Diese Implementierung überprüft Taxonomiebegriffe, die Eltern-Kind- $wp->query_vars['category_name'] und wenn sie eine Übereinstimmung findet, weist sie den URL-Pfad (abzüglich führender und $wp->query_vars['category_name'] Schrägstriche) zu $wp->query_vars['category_name'] , $wp->query_vars['tag'] oder $wp->query_vars['taxonomy'] & $wp->query_vars['term'] und umgeht die parse_request() -Methode der WP class.

Wenn der URL-Pfad jedoch nicht mit einem Begriff aus einer von Ihnen angegebenen Taxonomie übereinstimmt, wird die URL-Routing-Logik an das WordPress- parse_request() delegiert, indem die parse_request() -Methode der WP class parse_request() .

Um WP_Extended für Ihren Anwendungsfall verwenden zu können, müssen Sie die function register_url_route() in der Datei functions.php Ihres Themes wie WP_Extended aufrufen:

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

Was ist hier der Quellcode für das 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-Höhle # 1

Obwohl diese Technik für eine bestimmte Seite meiner Meinung nach hervorragend funktioniert, sollte diese Technik NIEMALS für ein Plugin verwendet werden, das auf WordPress.org verteilt wird, damit andere es verwenden können . Wenn es im core eines Softwarepakets basierend auf WordPress ist, dann könnte das in Ordnung sein. Andernfalls sollte diese Technik darauf beschränkt sein, das URL-Routing für eine bestimmte Site zu verbessern.

Warum? Weil nur ein Plugin diese Technik verwenden kann . Wenn zwei Plugins versuchen, es zu verwenden, werden sie miteinander in Konflikt geraten.

Nebenbei kann diese Strategie erweitert werden, um praktisch jedes Anwendungsfallmuster, das erforderlich sein könnte, generisch zu handhaben, und das beabsichtige ich umzusetzen, sobald ich entweder die Freizeit oder einen Kunden finde, der die benötigte Zeit sponsern kann Erstellen Sie vollständig generische Implementierungen.

Höhle # 2

Ich habe dies geschrieben, um parse_request() zu überschreiben, was eine sehr große function ist, und es ist durchaus möglich, dass ich eine Eigenschaft oder zwei des globalen $wp Objekts vermisse, das ich hätte setzen sollen. Also wenn etwas wackelig ist, lass es mich wissen und ich Ich werde es gerne recherchieren und die Antwort gegebenenfalls überarbeiten.

Sowieso…

Einfach, wirklich.

Schritt 1: Stoppen Sie die Verwendung des Rewrite-Parameters überhaupt. Wir werden Ihre eigenen Umschreibungen durchführen.

 'rewrite'=>false; 

Schritt 2: Legen Sie ausführliche Seitenregeln fest. Dies erzwingt, dass normale Seiten ihre eigenen Regeln haben, anstatt ein Catch-All am Ende der Seite zu sein.

Schritt 3: Erstellen Sie einige Umschreibungsregeln für Ihre Anwendungsfälle.

Schritt 4: Erzwingen Sie manuell eine Flush-Regeln. Einfachster Weg: Gehe zu Einstellungen-> Permalink und klicke auf den Speichern Button. Ich bevorzuge dies über eine Plugin-Aktivierungsmethode für meine eigene Verwendung, da ich die Regeln erzwingen kann, wenn ich die Dinge ändere.

Also, Code Zeit:

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

Denken Sie daran, dass Sie nach dem Hinzufügen dieses Codes aktiv sein müssen, wenn Sie die Permalink-Regeln leeren (indem Sie die Seite unter Einstellungen-> Permalinks speichern)!

Nachdem Sie die Regeln geleert und in der database gespeichert haben, sollte / whatever zu Ihrem Forum gehen = welche Taxonomieseite auch immer.

Rewrite-Regeln sind wirklich nicht so schwierig, wenn Sie reguläre Ausdrücke verstehen. Ich benutze diesen Code, um mir beim Debuggen zu helfen:

 function test_foot() { global $wp_rewrite; echo '
'; var_dump($wp_rewrite->rules); echo '

'; } add_action('wp_footer','test_foot');

Auf diese Weise kann ich die aktuellen Regeln auf einen Blick auf meiner Seite sehen. Denken Sie daran, dass das System bei jeder beliebigen URL am Anfang der Regeln beginnt und diese durchsucht, bis es eine passende gefunden hat. Die Übereinstimmung wird dann verwendet, um die Abfrage in eine normalere “key = value” -Struktur umzuschreiben. Diese Schlüssel werden analysiert, was in das WP_Query-Objekt gelangt. Einfach.

Edit: Side Note, diese Methode wird wahrscheinlich nur funktionieren, wenn Ihre normale benutzerdefinierte Post-Struktur mit etwas beginnt, das kein Catchall ist, wie% category% oder ähnliches. Sie müssen es mit einer statischen Zeichenfolge oder einem numerischen Zeichen wie% year% beginnen. So verhindern Sie, dass Ihre URL abgefangen wird, bevor sie Ihren Regeln entspricht.

Sie können dies nicht mit WP_Rewrite alleine durchführen, da es nicht zwischen Term-Slugs und Post-Slugs unterscheiden kann.

Sie müssen auch in ‘request’ einhaken und das 404 verhindern, indem Sie die post-Abfrage var anstelle der Taxonomie setzen.

Etwas wie das:

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

Beachten Sie, dass die Taxonomie vor dem Post-Typ definiert werden muss.

Dies wäre ein guter Zeitpunkt, um darauf hinzuweisen, dass eine Taxonomie und ein Post-Typ mit derselben Abfrage-Variable eine schlechte Idee ist.

Außerdem werden Sie nicht in der Lage sein, Posts zu erreichen, die den gleichen Slug wie einen der Begriffe enthalten.

Ich würde mir den Code des Top-Level-Katzen-Plugins ansehen:

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

Du könntest das leicht anpassen, also suchst du nach deiner Taxonomie Slug, indem du die

 $category_base = get_option('category_base'); 

in Zeile 74 zu etwas wie:

 $category_base = 'forums'; 

Ich würde vorschlagen, dass Sie sich das Plugin für benutzerdefinierte Post-Permalinks ansehen. Ich habe momentan keine Zeit, um zu testen, aber es kann mit deiner Situation helfen.

Da ich mit Ihrer anderen Frage vertraut bin, werde ich darauf antworten.

Ich habe dies noch nicht getestet, aber es könnte funktionieren, wenn Sie dies einmal ausführen, nachdem Sie alle gewünschten functionen registriert haben:

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

Was das bedeutet: Es entfernt die Rewrite-Regeln, die aus dem Themen-Permalink generiert wurden, aus dem normalen Ablauf des Regelarrays und führt sie am Ende des Arrays wieder zusammen. Dies verhindert, dass diese Regeln irgendwelche anderen Umschreibungsregeln stören. Als Nächstes erzwingt es ausführliche Umschreibungsregeln (jede Seite erhält eine individuelle Regel mit einem bestimmten regulären Ausdruck). Dies verhindert, dass die Seiten die Regeln Ihres Themas beeinträchtigen. Schließlich führt es einen harten Flush aus (stellen Sie sicher, dass Ihre .htaccess-Datei beschreibbar ist, sonst wird das nicht funktionieren) und speichert das sehr große, sehr komplizierte Array von Rewrite-Regeln.

Dafür gibt es ein Plugin .

Er entfernt den Typ-Slug, indem er für jede benutzerdefinierte Post-Typ-Seite eine spezifische Regel hinzufügt.

Nicht sicher, ob dies für Taxonomien funktioniert, aber es funktionierte für benutzerdefinierte Post-Typen

Obwohl es seit 2 Jahren nicht mehr aktualisiert wurde, funktionierte das folgende Plugin für mich: http://wordpress.org/plugins/remove-slug-from-custom-post-type/

FYI Ich 3.9.1 WP 3.9.1 mit WP-Typen 1.5.7

Verwenden Sie einen Schrägstrich als Wert für Slug … 100% funktioniert

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