解决方案


我使用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/


我如何使用add_rewrite_rule()
我需要传递设计者ID(出价)。

更新1

使用re.write规则而没有在URL中显示该怎么办?我发现这更具解释性。但这不起作用:

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=&bid= [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是的,我发贴后发现(我忘记了)。现在我也更好地了解了您的建议。在这里查看我的更新代码。我的设计师仍然是自定义数据库中的条目。是否可以使用POST指示或GET传递出价?

如果我复制链接并将其发送给其他人,则无法使用POST请求。使条块唯一并从那里查找数据是否有问题?

@Jan Fabry:ug是什么意思? `使用出价而不是设计者,检索设计者数据要容易得多

#1 楼

重写规则的一些背景知识

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()上调用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友好版本(不带空格或特殊字符)称为slug: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()函数似乎对他不起作用。

评论


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

– Jan Fabry
2010-12-16 10:35

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

– Jan Fabry
2010-12-16 10:52

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

– Jan Fabry
2010-12-16 11:05

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

–史蒂文
2010-12-16 11:23

@Steven:是的,的确如此:重写规则处理传入的链接,并且(仅在少数选定的情况下)不会影响代码中生成的链接。

– Jan Fabry
2010-12-16 11:32