需要有关add_rewrite_rule的帮助


55


我使用了Update 3,并使其正常运行。我的理解有误,是,我认为,一个重写规则将改变designers/?designer=some-designer&bid=9/designers/some-designer。但这当然是相反的。


我一直在做一些研究,但是我不太了解如何使用add_rewrite_rule()

这篇文章非常接近我所需要的,但是我真的需要那么多代码吗?

我当前的链接是:
http : //www.norwegianfashion.no/designers/
?designer=Batlak- og- Selvig& bid=9我想要的是这个
http://www.norwegianfashion.no/designers/Batlak-og-Selvig /

  1. 如何使用add_rewrite_rule()
  2. 我需要传递设计者ID(出价)。当使用重写规则而不在URL中显示规则时,该怎么办?

更新1

我发现这更具解释性。但这不起作用:

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

更新2

这是我尝试过的另一种解决方案,Jan Fabry在另一个线程中建议使用。我将其放在我的functions.php中,但没有效果。

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;
}

更新3
也在这里找到了一些示例。但这也不起作用:(

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;
}

更新4 我也尝试了此解决方案,但仍然没有成功。

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

}

更新5
似乎未添加我的重写规则。执行以下新规则:print_r($wp_rewrite),不包括我的新重写规则。

更新6
我测试了Jan的解决方案。但是URL不会改变:(

/* 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;
}

真的很感激,如果有人能够帮我解决这个问题。


这看起来与您在这里提出的第一个问题非常相似,对此我给出了答案。从那以后情况发生了变化,所以我的答案不再有效了吗?如果您不想在URL中使用设计器ID,则需要自己将“子弹”转换为ID,WordPress无法为您完成此操作。设计师仍然是外部对象吗?
Jan Fabry 2010年

@Jan Fabry是的,我发贴后发现(我忘记了)。现在我也更好地了解了您的建议。在这里查看我的更新代码。我的设计师仍然是自定义数据库中的条目。是否可以使用POST指示GET传递bid
史蒂文2010年

如果我复制链接并将其发送给其他人,则使用POST请求不会令人担心。使条块唯一并从那里查找数据是否有问题?
Jan Fabry 2010年

@Jan Fabry:你是什么意思slug?`使用检索Designer数据要容易bid得多designer
Steven

Answers:


87

重写规则的一些背景

WP Rewrite系统看起来很复杂,但实际上并不难理解它的工作原理。它用于解析漂亮的 URL(/designers/),就好像它们不是漂亮的(/index.php?pagename=designers)。基本思想是,您具有一系列重写规则,可以与传入URL匹配的正则表达式,并将它们重写为其他URL,大多数形式为index.php带有一些查询变量。这些变量设置为正则表达式中与URL匹配的部分。规则从上到下进行评估,因此,如果两个规则可能匹配,则第一个“获胜”。

这些重写规则通过调用存储在数据库中flush_rewrite_rules(),但是由于生成和编写这些规则是一项昂贵的操作,因此您不应在每一个上进行操作init。相反,您只能在更改规则时执行此操作:可能是在插件激活时(使用register_activation_hook()),或者是通过访问“ 永久链接”设置页面手动进行的(因为很难在主题激活时自动执行此操作)。如果不刷新规则,则调用add_rewrite_rule()无效。即使刷新了规则,也可以调用add_rewrite_rule()every init

添加重写规则的方法有很多种,如果只想添加一个规则,可以使用add_rewrite_rule()。因为对于文章,页面,分类规则,...产生多个规则,它们与高级功能创建像add_rewrite_tag()add_permastruct()...但这些都不需要我们这里的简单情况。

还有一些过滤器,因此您也可以使用generate_rewrite_rulesgenerate_rewrite_rules_array挂钩添加规则。这些使您可以对完整规则进行非常详细的控制,但是add_rewrite_rule()如果您只想添加一个规则,就足够了。

我创建了一个小插件,可让您分析当前的重写规则,(当然)我建议您在尝试更改任何内容时使用它。

从URL获取您的额外信息

让我们以您给出的示例为基础。您拥有设计师品牌Batlak og Selvig,并带有数字ID(bid9。您不需要URL中的此ID,而只需要名称。我们叫这个名字的URL的版本(无空格或特殊字符)的蛞蝓Batlak-og-Selvig

通常,URL应包含所有信息,以标识要在页面上显示的内容。您可以使用Cookie或POST请求来存储要显示的实际设计者ID,但是如果有人共享该链接(通过邮件,Facebook,Twitter或通过电话将其大声读出),则该链接将失效。如果您不想在URL中使用数字ID,则应确保该段是唯一的:然后您首先根据段对ID进行查找,然后像以前一样继续操作。

因此,我们现在了解到的是,我们想为模式“”/designers//添加一个重写规则,后跟所有内容,直到“下一个,并将该“任何内容”保存在designer_slug查询变量中。就您的情况而言,我相信您也希望将带有条的页面designers用作常规页面内容,因此我们也将告诉WordPress。

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

剩下要做的唯一一件事就是告诉WordPress也将保留designer_slug在查询变量中,以便以后可以访问它。WordPress使用允许的查询变量白名单,以防止人们通过URL修改帖子查询的每个参数。不在此列表中的所有内容都将被忽略。只需插入query_vars钩子并添加额外的变量即可:

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

如您所见,这个答案与我之前的答案基本相同,但是代码中没有刷新规则(因此您可以在主题的主题中functions.php而不是插件中使用它),并且有了更多的确定性和解释,因为我学到了自从(因为)回答了第一个问题以来,有关重写规则的内容很多。

聊天室讨论

我们在聊天室中解决了这个问题的最终问题。最后,史蒂文使用了generate_rewrite_rules钩子,因为该add_rewrite_rule()功能似乎对他不起作用。


2
@Steven:pagename是您要显示的WordPress页面(记录在数据库中)。然后,该页面可以designers.php在WP管理区域中指示它要使用模板文件。因此,您指向的是页面信息,而不是模板名称,因为同一模板可以用于多个页面:在这种情况下,WordPress不知道您想做什么。
Jan Fabry 2010年

1
@Steven:我认为您过于复杂地设置了挂钩。删除该add_rewrite_rules()函数并add_filter()/add_action()直接调用。如果这在主题文件中,请删除,flush_rewrite_rules()然后访问永久链接设置页面以刷新规则(或将其添加wpse5413_init()并稍后删除它们)。我的插件显示了当前的重写规则。请记住,这仅会更改传入URL的处理方式,而不会更改代码在HTML中写入URL的方式。
Jan Fabry 2010年

1
@Steven:我认为您甚至不必点击“保存”按钮,只需打开永久链接页面也将其刷新。同样,这只会增加WordPress接受/designers/designer-slug/URL的功能,您需要更改自己在HTML中编写这些URL的位置。通过/designers/Batlak-og-Selvig/自己进行测试(如果可行),找到生成这些URL的所有位置,并将其更改为使用新结构。
Jan Fabry 2010年

1
嗯,现在我想我开始了解了。我认为重写规则将改变URL在浏览器URL字段中的显示方式。但是,这意味着我必须实际输出URL www.mysite.com/batlat-og-selvig/9,然后将其“翻译”为/?designer=Batlak-og-Selvig&bid=9
Steven

1
@Steven:是的,的确如此:重写规则处理传入的链接,并且(仅在少数选定的情况下)不会影响代码中生成的链接。
Jan Fabry '12
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.