Cần trợ giúp với add_rewrite_rule


55

GIẢI PHÁP


Tôi đã đi với Bản cập nhật 3 và đã làm cho nó hoạt động. Điều tôi đã hiểu lầm là tôi tin rằng một quy tắc viết lại sẽ thay đổi designers/?designer=some-designer&bid=9thành /designers/some-designer. Nhưng tất nhiên đó là cách khác.


Tôi đã thực hiện một số nghiên cứu, nhưng tôi hoàn toàn không biết cách sử dụng add_rewrite_rule () .

Bài đăng này khá gần với những gì tôi cần, nhưng tôi có thực sự cần nhiều mã không?

Liên kết hiện tại của tôi là thế này:
http://www.norwegianfashion.no/designers/?designer=Batlak-og-Selvig&bid=9
Những gì tôi muốn đây là
http://www.norwegianfashion.no/designers/Batlak-og-Selvig /

  1. Làm thế nào để tôi sử dụng add_rewrite_rule()?
  2. Tôi cần phải vượt qua ID nhà thiết kế (giá thầu). Làm thế nào tôi có thể làm điều đó khi sử dụng các quy tắc re.write mà không hiển thị trong URL?

Cập nhật 1

Tôi tìm thấy điều này là một chút giải thích. Nhưng nó không hoạt động:

function add_rewrite_rules( $wp_rewrite ) 
{
    $new_rules = array(
        '('.$template_page_name.')/designers/(.*?)/?([0-9]{1,})/?$' => 'designers.php?designer='.
        $wp_rewrite->preg_index(1).'&bid='.
        $wp_rewrite->preg_index(2)
    );
       // Always add your rules to the top, to make sure your rules have priority
    $wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
}
add_action('generate_rewrite_rules', 'add_rewrite_rules');

function query_vars($public_query_vars) {

    $public_query_vars[] = "designer";
    $public_query_vars[] = "bid";
    return $public_query_vars;
}
add_filter('query_vars', 'query_vars')

Cập nhật 2

Đây là một giải pháp khác mà tôi đã thử, Jan Fabry gợi ý trong một chủ đề khác. Tôi đặt cái này trong hàm.php, nhưng nó không có tác dụng.

add_action('generate_rewrite_rules', 'add_rewrite_rules');
add_filter('query_vars', 'query_vars');

/* Custom re-write rules for desigenrs
------------------------------------------------------------------------------*/
function add_rewrite_rules( $wp_rewrite ) 
{
    add_rewrite_rule('^designers/([^/]*)/([^/]*)$ /designers/?designer=$1&bid=$2 [L]', 'top');
    flush_rewrite_rules(false);
}


function query_vars($public_query_vars) {

    $public_query_vars[] = "designer";
    $public_query_vars[] = "bid";
    return $public_query_vars;
}

Cập nhật 3
Tôi cũng tìm thấy một vài ví dụ ở đây . Nhưng điều này cũng không hoạt động :(

add_filter('rewrite_rules_array','wp_insertMyRewriteRules');
add_filter('query_vars','wp_insertMyRewriteQueryVars');
add_filter('init','flushRules');  

// Remember to flush_rules() when adding rules
function flushRules(){
    global $wp_rewrite;
    $wp_rewrite->flush_rules();
}

// Adding a new rule
function wp_insertMyRewriteRules($rules)
{
    $newrules = array();
    $newrules['(designers)/(\d*)$'] = 'index.php?pagename=designers&designer=$matches[1]';
    return $newrules + $rules;
}

// Adding the bid var so that WP recognizes it
function wp_insertMyRewriteQueryVars($vars)
{
    array_push($vars, 'designer');
    return $vars;
}

Cập nhật 4 Tôi cũng đã thử giải pháp này, nhưng vẫn không thành công.

add_filter('search_rewrite_rules', 'designers_createRewriteRules');

function designers_createRewriteRules($rewrite) {
global $wp_rewrite;

// add rewrite tokens
$designer_token = '%designers%';
$wp_rewrite->add_rewrite_tag($designer_token, '(.+)', 'designers=');

$bid_token = '%bid%';
$wp_rewrite->add_rewrite_tag($bid_token, '(.+)', 'bid=');

$keywords_structure = $wp_rewrite->root . "designers/$designer_token/$bid_token";
$keywords_rewrite = $wp_rewrite->generate_rewrite_rules($keywords_structure);

return ( $rewrite + $keywords_rewrite );

}

Cập nhật 5
Có vẻ như các quy tắc viết lại của tôi không được thêm vào. Thực hiện các quy tắc mới sau khi phát ra các quy tắc mới : print_r($wp_rewrite), không bao gồm các quy tắc viết lại mới của tôi.

Cập nhật 6
Tôi đã thử nghiệm giải pháp của Jan. Nhưng URL không thay đổi :(

/* Initiation script for NF template
------------------------------------------------------------------------------*/   
add_action('after_setup_theme','norwegianfashion_setup');

if ( ! function_exists( 'norwegianfashion_setup' ) ):

  function norwegianfashion_setup() { 
    /* Here I do a lot of stuff */

    // SEO friendly URL for desigenrs
    add_action( 'init', 'wpa5413_init' );
    add_filter( 'query_vars', 'wpa5413_query_vars' );
  }

endif;


/* Custom re-write rules for desigenrs
------------------------------------------------------------------------------*/
function wpa5413_init()
{
    // Remember to flush the rules once manually after you added this code!
    add_rewrite_rule(
        'designers/([^/]+)/?',
        'index.php?pagename=designers&designer=$matches[1]',
        'top' );
}

function wpa5413_query_vars( $query_vars )
{
    $query_vars[] = 'designer';
    return $query_vars;
}

Tôi thực sự sẽ đánh giá cao nó nếu ai đó có thể giúp tôi giải quyết vấn đề này.


Điều này trông rất giống với câu hỏi đầu tiên bạn hỏi ở đây, và tôi đã trả lời . Tình hình đã thay đổi kể từ đó, vì vậy câu trả lời của tôi không còn giá trị nữa? Nếu bạn không muốn ID nhà thiết kế trong URL của mình, bạn sẽ cần phải tự chuyển đổi "con sên" thành ID, WordPress không thể làm điều này cho bạn. Các nhà thiết kế vẫn là một đối tượng bên ngoài?
Jan Fabry

@Jan Fabry Vâng, tôi phát hiện ra rằng sau khi tôi đăng bài này (tôi đã quên). Bây giờ tôi hiểu bạn đề nghị tốt hơn. Xem mã cập nhật của tôi ở đây. Các nhà thiết kế của tôi vẫn là các mục trong một DB tùy chỉnh. Có thể sử dụng POST insteed og GET để vượt qua bid?
Steven

Sử dụng một yêu cầu POST sẽ không worj nếu tôi sao chép liên kết và gửi nó cho người khác. Có phải là một vấn đề để làm cho sên độc đáo và thực hiện tra cứu dữ liệu từ đó?
Jan Fabry

@Jan Fabry: Ý bạn là sluggì? `Truy xuất dữ liệu Nhà thiết kế dễ dàng hơn nhiều bằng cách sử dụng bidthay vìdesigner
Steven

Câu trả lời:


87

Một số nền tảng về quy tắc viết lại

Hệ thống WP Rewrite có vẻ phức tạp, nhưng thực tế không khó để hiểu nó hoạt động như thế nào. Nó được sử dụng để phân tích các URL đẹp ( /designers/) như thể chúng không đẹp ( /index.php?pagename=designers). Ý tưởng cơ bản là bạn có một danh sách các quy tắc viết lại , các biểu thức chính quy có thể khớp với các URL đến và viết lại chúng thành các URL khác, chủ yếu ở dạng index.phpvới một số biến truy vấn. Các biến này được đặt thành các phần của biểu thức chính quy khớp với URL. Các quy tắc được đánh giá từ trên xuống dưới, vì vậy nếu hai quy tắc có thể khớp với nhau, quy tắc đầu tiên sẽ "thắng".

Các quy tắc viết lại này được lưu trữ trong cơ sở dữ liệu bằng cách gọi flush_rewrite_rules(), nhưng vì việc tạo và viết các quy tắc này là một hoạt động tốn kém, bạn không nên thực hiện trên mọi cơ sở init. Thay vào đó, bạn chỉ làm điều đó khi bạn thay đổi các quy tắc: có thể là kích hoạt plugin (sử dụng register_activation_hook()) hoặc thủ công bằng cách truy cập trang cài đặt Permalinks ( vì khó có thể tự động thực hiện việc này khi kích hoạt chủ đề ). Nếu bạn không tuôn ra các quy tắc, gọi add_rewrite_rule()sẽ không có hiệu lực. Không có vấn đề gì để gọi add_rewrite_rule()cho mọi init, ngay cả sau khi bạn tuôn ra các quy tắc.

Có nhiều cách để thêm quy tắc viết lại của bạn và nếu bạn chỉ muốn thêm một quy tắc, bạn có thể thực hiện việc này với add_rewrite_rule(). Bởi vì các quy tắc cho bài viết, trang, nguyên tắc phân loại, ... dẫn đến nhiều quy tắc, họ được tạo ra với các chức năng cao cấp như add_rewrite_tag(), add_permastruct(), ... Tuy nhiên, những điều này không cần thiết đối với trường hợp đơn giản chúng ta có ở đây.

Ngoài ra còn có một số bộ lọc, vì vậy bạn cũng có thể thêm quy tắc của mình bằng cách sử dụng generate_rewrite_ruleshoặc generate_rewrite_rules_arrayhook. Những điều này cung cấp cho bạn quyền kiểm soát rất chi tiết đối với các quy tắc hoàn chỉnh, nhưng một lần nữa, add_rewrite_rule()là đủ nếu bạn chỉ muốn thêm một quy tắc.

Tôi đã tạo một plugin nhỏ cho phép bạn phân tích các quy tắc viết lại hiện tại và (tất nhiên) tôi khuyên bạn nên sử dụng nó khi bạn cố gắng thay đổi bất cứ điều gì.

Nhận thêm thông tin của bạn từ URL

Hãy xây dựng dựa trên ví dụ bạn đã đưa ra. Bạn có thương hiệu thiết kế Batlak og Selvig, với ID số ( bid) 9. Bạn không muốn ID này trong URL mà chỉ có tên. Chúng tôi gọi phiên bản thân thiện với URL của tên (không có dấu cách hoặc ký tự đặc biệt) là sên : Batlak-og-Selvig.

Nói chung, URL phải chứa tất cả thông tin để xác định nội dung bạn muốn hiển thị trên trang. Bạn có thể sử dụng cookie hoặc yêu cầu POST để lưu trữ ID nhà thiết kế thực tế mà bạn muốn hiển thị, nhưng điều này sẽ bị hỏng nếu bất kỳ ai chia sẻ liên kết, bằng cách gửi nó qua thư, Facebook, Twitter hoặc chỉ đọc to qua điện thoại. Nếu bạn không muốn sử dụng ID số trong URL của mình, bạn nên đảm bảo sên là duy nhất: trước tiên bạn thực hiện tra cứu ID dựa trên sên và tiếp tục như bạn đã làm trước đó.

Vì vậy, những gì chúng ta đã học bây giờ là chúng ta muốn thêm quy tắc viết lại cho mẫu " /designers/theo sau là bất cứ điều gì tiếp theo /" và lưu "bất cứ điều gì" vào designer_slugbiến truy vấn. Trong trường hợp của bạn, tôi tin rằng bạn cũng muốn sử dụng trang với slug designerslàm nội dung trang chung, vì vậy chúng tôi cũng sẽ nói với WordPress điều đó.

add_action( 'init', 'wpa5413_init' );
function wpa5413_init()
{
    // Remember to flush the rules once manually after you added this code!
    add_rewrite_rule(
        // The regex to match the incoming URL
        'designers/([^/]+)/?',
        // The resulting internal URL: `index.php` because we still use WordPress
        // `pagename` because we use this WordPress page
        // `designer_slug` because we assign the first captured regex part to this variable
        'index.php?pagename=designers&designer_slug=$matches[1]',
        // This is a rather specific URL, so we add it to the top of the list
        // Otherwise, the "catch-all" rules at the bottom (for pages and attachments) will "win"
        'top' );
}

Điều duy nhất còn lại phải làm là bảo WordPress cũng giữ các designer_slugbiến truy vấn, để bạn có thể truy cập nó sau. WordPress sử dụng danh sách trắng các biến truy vấn được phép, để ngăn mọi người sửa đổi mọi tham số của truy vấn bài đăng qua URL. Tất cả mọi thứ không có trong danh sách này được bỏ qua. Chỉ cần móc vào query_varshook và thêm biến phụ của bạn:

add_filter( 'query_vars', 'wpa5413_query_vars' );
function wpa5413_query_vars( $query_vars )
{
    $query_vars[] = 'designer_slug';
    return $query_vars;
}

Như bạn có thể thấy, câu trả lời này về cơ bản giống như câu trả lời trước của tôi , nhưng không có quy tắc tuôn ra trong mã (vì vậy bạn có thể sử dụng nó trong chủ đề của mình functions.phpthay vì plugin), và với một chút chắc chắn và giải thích hơn vì tôi đã học được rất nhiều về việc viết lại các quy tắc kể từ khi (và vì) trả lời câu hỏi đầu tiên của bạn.

Phòng thảo luận

Chúng tôi đã làm rõ các vấn đề cuối cùng cho câu hỏi này trong phòng trò chuyện . Cuối cùng, Steven đã sử dụng generate_rewrite_ruleshook, bởi vì add_rewrite_rule()chức năng này dường như không hoạt động với anh ta.


2
@Steven: pagenamelà sên của trang WordPress bạn muốn hiển thị (ghi trong cơ sở dữ liệu). Trang này sau đó có thể cho biết nó muốn sử dụng designers.phptệp mẫu trong khu vực quản trị WP. Vì vậy, bạn trỏ đến slug trang, không phải tên mẫu, vì cùng một mẫu có thể được sử dụng cho nhiều trang: trong trường hợp này WordPress không biết bạn muốn làm gì.
Jan Fabry

1
@Steven: Tôi nghĩ bạn quá phức tạp trong cách bạn thiết lập các hook. Hủy bỏ add_rewrite_rules()chức năng và gọi add_filter()/add_action()trực tiếp. Nếu đây là trong một tệp chủ đề, hãy xóa flush_rewrite_rules()và chỉ cần truy cập trang cài đặt permalinks để xóa các quy tắc (hoặc thêm chúng vào wpse5413_init()và xóa chúng sau). Và plugin của tôi hiển thị các quy tắc viết lại hiện tại. Hãy nhớ rằng điều này chỉ thay đổi cách xử lý URL đến chứ không phải cách mã của bạn sẽ viết URL trong HTML.
Jan Fabry

1
@Steven: Tôi không nghĩ bạn thậm chí phải nhấn nút lưu, chỉ cần mở trang permalinks cũng sẽ xóa nó. Và một lần nữa, điều này sẽ chỉ thêm khả năng để WordPress chấp nhận /designers/designer-slug/URL, bạn cần thay đổi địa điểm nơi bạn tự viết các URL này trong HTML của mình. Kiểm tra nó bằng cách tự đi /designers/Batlak-og-Selvig/, nếu điều đó hoạt động, tìm tất cả các địa điểm tạo các URL này và thay đổi chúng để sử dụng cấu trúc mới.
Jan Fabry

1
Ah, bây giờ tôi nghĩ rằng tôi đang bắt đầu hiểu. Tôi nghĩ rằng các quy tắc viết lại sẽ thay đổi cách URL được phân phối trong trường URL của trình duyệt. Nhưng điều có nghĩa là tôi phải thực sự xuất URL www.mysite.com/batlat-og-selvig/9và sau đó nó được "dịch" thành/?designer=Batlak-og-Selvig&bid=9
Steven

1
@Steven: Có, thực sự: các quy tắc viết lại xử lý các liên kết đến và (chỉ trong một vài trường hợp được chọn) không ảnh hưởng đến các liên kết được tạo trong mã của bạn.
Jan Fabry
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.