CẬP NHẬT
Kể từ khi viết lõi WordPress này đã thêm 'do_parse_request'
móc cho phép định tuyến URL được xử lý một cách thanh lịch và không cần phải mở rộng WP
lớp. Tôi đã đề cập sâu vào chủ đề trong bài nói chuyện Atlanta WordCamp 2014 của tôi có tên " Định tuyến URL cứng " ; các slide có sẵn tại liên kết.
CÂU TRẢ LỜI
Thiết kế URL rất quan trọng trong hơn một thập kỷ; Tôi thậm chí đã viết một blog về nó vài năm trước. Và trong khi WordPress là một phần mềm tuyệt vời thì thật không may , hệ thống viết lại URL của nó chỉ thiếu não (IMHO, tất nhiên. :) Dù sao, rất vui khi thấy mọi người quan tâm đến thiết kế URL!
Câu trả lời tôi sẽ cung cấp là một plugin tôi đang gọi WP_Extended
đó là bằng chứng về khái niệm cho đề xuất này trên Trac (Lưu ý rằng đề xuất bắt đầu như một thứ và phát triển thành một thứ khác, vì vậy bạn phải đọc toàn bộ để xem nó đã đứng đầu.)
Về cơ bản, ý tưởng là phân WP
lớp lớp, ghi đè parse_request()
phương thức và sau đó gán $wp
biến toàn cục với một thể hiện của lớp con. Sau đó, bên trong parse_request()
bạn thực sự kiểm tra đường dẫn theo phân đoạn đường dẫn thay vì sử dụng danh sách các biểu thức chính quy phải khớp với toàn bộ URL.
Vì vậy, để nói rõ, kỹ thuật này chèn logic trước parse_request()
kiểm tra các kết quả khớp URL-Reg-RegEx và thay vào đó trước tiên tìm các kết quả khớp thuật ngữ phân loại, nhưng nó CHỈ thay thế parse_request()
và giữ nguyên toàn bộ phần còn lại của hệ thống định tuyến URL WordPress bao gồm và đặc biệt là việc sử dụng $query_vars
biến.
Đối với trường hợp sử dụng của bạn, việc triển khai này chỉ so sánh các phân đoạn đường dẫn URL với các thuật ngữ phân loại vì đó là tất cả những gì bạn cần. Điều này thực hiện kiểm tra về phân loại tôn trọng mối quan hệ lâu cha-con và khi nó tìm thấy một trận đấu nó gán đường dẫn URL (trừ ở đầu và đuôi dấu gạch chéo) để $wp->query_vars['category_name']
, $wp->query_vars['tag']
hoặc $wp->query_vars['taxonomy']
& $wp->query_vars['term']
và nó đi qua các parse_request()
phương pháp của WP
lớp.
Mặt khác, nếu đường dẫn URL không khớp với một thuật ngữ từ phân loại học, bạn đã chỉ định nó ủy quyền logic định tuyến URL cho hệ thống viết lại WordPress bằng cách gọi parse_request()
phương thức của WP
lớp.
Để sử dụng WP_Extended
cho trường hợp sử dụng của bạn, bạn sẽ cần gọi register_url_route()
hàm từ trong functions.php
tệp chủ đề của mình như sau:
add_action('init','init_forum_url_route');
function init_forum_url_route() {
register_url_route(array('taxonomy'=>'forum'));
}
Mã nguồn của plugin là gì:
<?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
Mặc dù đối với một trang web nhất định tôi nghĩ rằng kỹ thuật này hoạt động rất tốt nhưng kỹ thuật này KHÔNG BAO GIỜ được sử dụng cho một plugin được phân phối trên WordPress.org cho người khác sử dụng . Nếu đó là cốt lõi của gói phần mềm dựa trên WordPress thì điều đó có thể ổn. Mặt khác, kỹ thuật này nên được giới hạn để cải thiện định tuyến URL cho một trang web cụ thể .
Tại sao? Bởi vì chỉ có một plugin có thể sử dụng kỹ thuật này . Nếu hai plugin cố gắng sử dụng, chúng sẽ xung đột với nhau.
Vì một bên, chiến lược này có thể được mở rộng để xử lý một cách tổng quát mọi mô hình trường hợp sử dụng có thể được yêu cầu và đó là điều tôi dự định thực hiện ngay khi tôi tìm thấy thời gian rảnh rỗi hoặc khách hàng có thể tài trợ thời gian cần thiết xây dựng thực hiện hoàn toàn chung chung.
CÁCH SỐ 2
Tôi đã viết cái này để ghi đè lên parse_request()
một chức năng rất lớn và hoàn toàn có khả năng tôi đã bỏ lỡ một hoặc hai tài sản toàn cầu $wp
mà tôi nên đặt .. Vì vậy, nếu có hành động nào đó, hãy cho tôi biết và tôi sẽ rất vui nghiên cứu nó và sửa lại câu trả lời nếu cần.
Dù sao...
'slug' => 'forums'
trống chỉ cần loại bỏ nó hoàn toàn và chỉ có'rewrite' => array('with_front' => false, 'hierarchical' => true)
? Tôi nghĩ rằng điều đó đã làm việc trong quá khứ cho tôi. Cũng chắc chắn rằng bạn tuôn ra permalinks.