阐述 WordPress `add_rewrite_rule()` 函数的源码:如何创建自定义 URL 重写规则,并解释其在数据库中的存储。

好家伙,这题目够硬核! 各位听众,今天咱们就来聊聊 WordPress 里的 URL 重写,特别是 add_rewrite_rule() 这个神奇的函数。准备好了吗?要开车啦!

URL 重写:不只改头换面,更是灵魂重塑

首先,我们要明白啥叫 URL 重写。简单来说,就是把一个看起来很丑陋、很复杂的 URL 变成一个更漂亮、更友好的 URL。这就像给一个人化了个妆,但实际上,这个人还是那个人,背后的程序逻辑并没有改变。

例如,假设我们想把 index.php?page=my-custom-page 变成 my-custom-page/。这就是 URL 重写的魅力。

add_rewrite_rule():URL 重写的利器

add_rewrite_rule() 是 WordPress 提供的用于添加自定义 URL 重写规则的函数。它的基本用法如下:

add_rewrite_rule( $regex, $redirect, $priority );
  • $regex:这是一个正则表达式,用于匹配原始 URL。
  • $redirect:这是重定向到的 URL,通常包含一些占位符,这些占位符会被 $regex 中匹配到的内容替换。
  • $priority:可选参数,指定规则的优先级,topbottomtop 优先级高,规则会先被匹配。默认是 bottom

案例分析:让 my-custom-page/ 闪亮登场

现在,让我们用 add_rewrite_rule() 来实现把 index.php?page=my-custom-page 变成 my-custom-page/ 的目标。

function my_custom_rewrite_rule() {
  add_rewrite_rule(
    '^my-custom-page/?$',  // 正则表达式,匹配 my-custom-page/ 或 my-custom-page
    'index.php?page=my-custom-page', // 重定向到的 URL
    'top' // 优先级
  );
}
add_action( 'init', 'my_custom_rewrite_rule' );

这段代码做了什么?

  1. 定义函数 my_custom_rewrite_rule():这是我们自定义的函数,用于添加重写规则。
  2. add_rewrite_rule():这是核心函数。
    • '^my-custom-page/?$':这个正则表达式匹配以 my-custom-page 开头,后面可以有也可以没有斜杠 /,然后以字符串结尾的 URL。 ^表示字符串的开始,$表示字符串的结束,?表示前面的字符可以出现0次或1次。
    • 'index.php?page=my-custom-page':这是重定向到的 URL。当 URL 匹配到正则表达式时,WordPress 会将 URL 重写成这个形式。
    • 'top':设置优先级为最高,确保我们的规则优先匹配。
  3. add_action( 'init', 'my_custom_rewrite_rule' ):这行代码将我们的函数挂载到 init 钩子上。init 钩子在 WordPress 初始化时触发,这意味着我们的重写规则会在 WordPress 启动时被添加。

重点:别忘了刷新固定链接!

添加重写规则后,必须刷新固定链接设置。这会告诉 WordPress 重新生成 .htaccess 文件(如果你的服务器使用 Apache)或更新 Nginx 的配置。刷新固定链接的方法是:进入 WordPress 后台 -> 设置 -> 固定链接,然后直接点击“保存更改”按钮即可。

更高级的用法:捕获 URL 中的参数

URL 重写的强大之处在于能够捕获 URL 中的参数。例如,我们想把 product/123/ 重写成 index.php?product_id=123

function my_custom_product_rewrite_rule() {
  add_rewrite_rule(
    '^product/([0-9]+)/?$', // 正则表达式,匹配 product/数字/
    'index.php?product_id=$matches[1]', // 重定向到的 URL,使用 $matches[1] 获取匹配到的数字
    'top'
  );
}
add_action( 'init', 'my_custom_product_rewrite_rule' );

这个例子中,([0-9]+) 是一个捕获组,它会匹配一个或多个数字。$matches[1] 用于获取第一个捕获组匹配到的内容(也就是数字 123)。

$matches 数组的奥秘

$matches 是一个数组,包含了正则表达式匹配到的所有内容。$matches[0] 包含完整的匹配字符串,$matches[1] 包含第一个捕获组匹配到的内容,$matches[2] 包含第二个捕获组匹配到的内容,以此类推。

例如,如果我们的正则表达式是 '^product/([0-9]+)/([a-z]+)/?$',并且 URL 是 product/123/abc/,那么:

索引 描述
0 product/123/abc/ 完整的匹配字符串
1 123 第一个捕获组匹配到的内容(数字)
2 abc 第二个捕获组匹配到的内容(小写字母)

add_rewrite_tag():让 WordPress 识别自定义查询变量

仅仅添加重写规则是不够的。WordPress 默认情况下不会识别自定义的查询变量(例如 product_id)。我们需要使用 add_rewrite_tag() 函数来告诉 WordPress 如何处理这些变量。

function my_custom_rewrite_tag() {
  add_rewrite_tag( '%product_id%', '([0-9]+)' );
}
add_action( 'init', 'my_custom_rewrite_tag' );
  • '%product_id%':这是查询变量的名称,前后需要加上百分号 %
  • '([0-9]+)':这是匹配查询变量值的正则表达式。

现在,我们可以这样获取 product_id 的值:

$product_id = get_query_var( 'product_id' );

flush_rewrite_rules():终极武器

有时候,即使刷新了固定链接,重写规则仍然没有生效。这时候,你可以尝试使用 flush_rewrite_rules() 函数来强制刷新重写规则。

function my_custom_flush_rewrite_rules() {
  flush_rewrite_rules();
}
add_action( 'after_switch_theme', 'my_custom_flush_rewrite_rules' );

这段代码会在主题切换后强制刷新重写规则。注意,flush_rewrite_rules() 函数会消耗一定的资源,所以不建议频繁调用。

URL 重写规则在数据库中的存储

WordPress 将 URL 重写规则存储在 wp_options 表中,选项名称是 rewrite_rules。这个选项的值是一个序列化的数组,包含了所有的重写规则。

你可以使用以下代码来查看存储的重写规则:

global $wpdb;
$rewrite_rules = get_option( 'rewrite_rules' );
echo '<pre>';
print_r( $rewrite_rules );
echo '</pre>';

generate_rewrite_rules():幕后英雄

当我们刷新固定链接时,WordPress 会调用 generate_rewrite_rules() 函数来生成新的重写规则。这个函数会遍历所有已注册的重写规则(包括通过 add_rewrite_rule() 添加的规则),并生成相应的正则表达式和重定向 URL。

.htaccess 文件:Apache 服务器的灵魂

如果你的服务器使用 Apache,WordPress 会将生成的重写规则写入到 .htaccess 文件中。.htaccess 文件允许你配置 Apache 服务器的行为,包括 URL 重写。

例如,一个简单的 .htaccess 文件可能包含以下内容:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /wordpress/
RewriteRule ^my-custom-page/?$ index.php?page=my-custom-page [L]
</IfModule>
  • RewriteEngine On:启用 URL 重写引擎。
  • RewriteBase /wordpress/:指定 WordPress 的安装目录。
  • RewriteRule ^my-custom-page/?$ index.php?page=my-custom-page [L]:定义重写规则。[L] 表示这是最后一个规则,如果匹配到这个规则,就不再继续匹配其他规则。

Nginx 配置:另一种选择

如果你的服务器使用 Nginx,你需要手动配置 Nginx 来实现 URL 重写。Nginx 的配置方式与 Apache 不同,需要使用 rewrite 指令。

例如,一个简单的 Nginx 配置可能如下:

server {
    listen 80;
    server_name example.com;
    root /var/www/wordpress;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    rewrite ^/my-custom-page/?$ /index.php?page=my-custom-page last;

    location ~ .php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.4-fpm.sock;
    }
}

最佳实践:避免冲突

在添加自定义重写规则时,一定要注意避免与其他规则冲突。否则,可能会导致 URL 无法正确解析。

以下是一些避免冲突的建议:

  • 使用唯一的正则表达式:确保你的正则表达式不会匹配到其他 URL。
  • 指定优先级:使用 $priority 参数来控制规则的优先级。
  • 测试你的规则:在生产环境中使用之前,先在测试环境中测试你的规则。

总结:URL 重写的艺术

URL 重写是一门艺术,它需要你对正则表达式、WordPress 内部机制以及服务器配置都有一定的了解。掌握了 URL 重写,你就可以创建更友好、更易于搜索引擎优化的 URL,从而提升你的网站的可用性和 SEO 效果。

常见问题解答

  • 为什么我的重写规则没有生效?
    • 确保你已经刷新了固定链接。
    • 检查你的正则表达式是否正确。
    • 检查你的重定向 URL 是否正确。
    • 尝试使用 flush_rewrite_rules() 函数。
    • 检查你的服务器配置(.htaccess 或 Nginx 配置)。
  • 如何调试 URL 重写规则?
    • 使用 var_dump()print_r() 函数来输出 $matches 数组,查看正则表达式匹配到的内容。
    • 使用 WordPress 的调试模式(WP_DEBUG)来查看错误信息。
    • 查看服务器的错误日志。

好了,今天的讲座就到这里。希望大家对 WordPress 的 URL 重写有了更深入的了解。下次有机会再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注