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

嘿,各位代码界的弄潮儿们,准备好一起探索 WordPress URL 重写的神秘世界了吗?今天我们就来扒一扒 add_rewrite_rule() 这个神奇的函数,看看它到底是怎么把咱们自定义的 URL 变成 WordPress 能够理解的“悄悄话”。

开场白:URL 重写,到底是个啥?

想象一下,你想要一个超级酷炫的 URL,比如 example.com/my-awesome-product。但是,你的产品信息可能实际上存储在数据库里,要通过类似 example.com/?product_id=123 这样的方式才能访问到。

这时候,URL 重写就派上用场了!它就像一个翻译官,把用户看到的酷炫 URL(example.com/my-awesome-product)翻译成 WordPress 内部能理解的真实 URL(example.com/?product_id=123)。这样,用户体验 UP UP UP,SEO 也跟着蹭蹭蹭往上涨!

add_rewrite_rule():URL 重写的魔法棒

add_rewrite_rule() 函数就是 WordPress 提供的魔法棒,让我们能够自定义 URL 重写的规则。它的基本语法是这样的:

add_rewrite_rule( string $regex, string $redirect, string $where = 'top' );
  • $regex 这是一个正则表达式,用来匹配你想要的酷炫 URL 模式。
  • $redirect 这是当 $regex 匹配成功时,要重定向到的真实 URL。
  • $where 可选参数,指定规则放置的位置,可以是 ‘top’ 或 ‘bottom’。’top’ 表示放在规则列表的顶部,优先匹配;’bottom’ 表示放在底部,最后匹配。

实战演练:让你的产品页面更性感

假设我们有一个自定义文章类型 product,我们想让它的 URL 变成 example.com/product/产品名称 这样的形式。

首先,我们需要创建一个自定义文章类型 product(如果还没有的话):

function create_product_post_type() {
  register_post_type( 'product',
    array(
      'labels' => array(
        'name' => __( 'Products' ),
        'singular_name' => __( 'Product' )
      ),
      'public' => true,
      'has_archive' => true,
      'rewrite' => array('slug' => 'product'), // 关键:设置slug为'product'
      'supports' => array( 'title', 'editor', 'thumbnail' ),
    )
  );
}
add_action( 'init', 'create_product_post_type' );

注意 rewrite 参数,我们设置 slugproduct。 这通常足够让你的产品页面通过 example.com/product/产品名称 访问。 但是,如果我们想要更灵活的控制,或者要添加其他参数呢? add_rewrite_rule() 就派上用场了。

现在,我们来添加重写规则:

function add_product_rewrite_rules() {
  add_rewrite_rule(
    '^product/([^/]*)/?', // 正则表达式:匹配 product/产品名称/ 这样的 URL
    'index.php?product=$matches[1]', // 重定向到 index.php,并设置 product 参数
    'top'
  );
}
add_action( 'init', 'add_product_rewrite_rules' );

代码解释:

  • *`^product/([^/])/?`:** 这个正则表达式是关键。
    • ^:表示 URL 的开头。
    • product/:匹配 URL 中的 "product/" 部分。
    • ([^/]*):这是一个捕获组,用括号括起来的部分会被捕获。
      • [^/]:表示除了斜杠 / 之外的任何字符。
      • *:表示匹配零个或多个前面的字符。所以 ([^/]*) 匹配 "product/" 之后的所有内容,直到下一个斜杠(如果有的话)。
    • /?:表示斜杠 / 可有可无。
  • index.php?product=$matches[1] 这是重定向到的 URL。
    • index.php:WordPress 的入口文件。
    • ?product=$matches[1]:设置 product 参数的值。$matches[1] 表示正则表达式中第一个捕获组的内容,也就是产品名称。
  • 'top' 将规则放在规则列表的顶部,优先匹配。

重要提示:刷新重写规则!

添加或修改重写规则后,必须刷新重写规则! 否则,WordPress 不知道你的新规则,URL 重写就不会生效。

刷新重写规则有两种方法:

  1. 手动刷新: 登录 WordPress 后台,进入 "设置" -> "固定链接",然后直接点击 "保存更改" 按钮。 即使你没有做任何修改,也要点击保存,这样 WordPress 就会重新生成 .htaccess 文件(如果你的服务器使用 Apache 的话)和更新数据库中的重写规则。

  2. 代码刷新: 你可以使用 flush_rewrite_rules() 函数在代码中刷新重写规则。 但是,不要在每次页面加载时都调用这个函数! 这会严重影响性能。 应该只在插件激活、主题切换等需要更新重写规则的时候调用。

function my_plugin_activation() {
  // 添加你的其他激活代码...

  flush_rewrite_rules();
}
register_activation_hook( __FILE__, 'my_plugin_activation' );

接收参数:在 WordPress 中获取产品名称

现在,当用户访问 example.com/product/我的产品 时,WordPress 会将请求重定向到 index.php?product=我的产品。 我们需要在 WordPress 中获取 product 参数的值,并根据这个值显示相应的产品信息。

function display_product() {
  global $wp_query;

  if ( isset( $wp_query->query_vars['product'] ) ) {
    $product_name = $wp_query->query_vars['product'];

    // 根据 $product_name 查询数据库,获取产品信息
    $product = get_product_by_name( $product_name ); // 假设有这样一个函数

    if ( $product ) {
      // 显示产品信息
      echo '<h1>' . $product->title . '</h1>';
      echo '<p>' . $product->description . '</p>';
      // ...
    } else {
      // 产品不存在
      echo '<h1>产品未找到</h1>';
    }
  }
}
add_action( 'template_redirect', 'display_product' );

代码解释:

  • global $wp_query; $wp_query 是 WordPress 的全局查询对象,包含了当前请求的所有信息,包括 URL 参数。
  • isset( $wp_query->query_vars['product'] ) 检查 product 参数是否存在。
  • $product_name = $wp_query->query_vars['product']; 获取 product 参数的值。
  • get_product_by_name( $product_name ) 这是一个假设的函数,用来根据产品名称查询数据库,获取产品信息。 你需要根据你的实际情况来实现这个函数。
  • template_redirect 这是一个 WordPress 的 action hook,在 WordPress 确定要使用哪个模板文件之前触发。 我们在这个 hook 中调用 display_product() 函数,以便在正确的页面上显示产品信息。

高级技巧:使用多个捕获组

正则表达式可以包含多个捕获组,让我们能够提取 URL 中多个部分的信息。

例如,假设我们想要一个更复杂的 URL 结构:example.com/product/产品类别/产品名称

function add_product_rewrite_rules() {
  add_rewrite_rule(
    '^product/([^/]*)/([^/]*)/?', // 正则表达式:匹配 product/产品类别/产品名称/ 这样的 URL
    'index.php?product_category=$matches[1]&product=$matches[2]', // 重定向到 index.php,并设置 product_category 和 product 参数
    'top'
  );
}
add_action( 'init', 'add_product_rewrite_rules' );

在这个例子中,我们使用了两个捕获组:

  • *`([^/])`:** 第一个捕获组匹配产品类别。
  • *`([^/])`:** 第二个捕获组匹配产品名称。

重定向 URL 中,我们使用 $matches[1]$matches[2] 分别获取产品类别和产品名称。

display_product() 函数中,我们需要同时获取 product_categoryproduct 参数的值:

function display_product() {
  global $wp_query;

  if ( isset( $wp_query->query_vars['product_category'] ) && isset( $wp_query->query_vars['product'] ) ) {
    $product_category = $wp_query->query_vars['product_category'];
    $product_name = $wp_query->query_vars['product'];

    // 根据 $product_category 和 $product_name 查询数据库,获取产品信息
    $product = get_product_by_category_and_name( $product_category, $product_name ); // 假设有这样一个函数

    if ( $product ) {
      // 显示产品信息
      echo '<h1>' . $product->title . '</h1>';
      echo '<p>类别:' . $product->category . '</p>';
      echo '<p>' . $product->description . '</p>';
      // ...
    } else {
      // 产品不存在
      echo '<h1>产品未找到</h1>';
    }
  }
}
add_action( 'template_redirect', 'display_product' );

add_rewrite_tag():让 WordPress 识别你的参数

在上面的例子中,我们直接使用了 $wp_query->query_vars['product'] 来获取参数值。 但是,在某些情况下,WordPress 可能无法识别我们自定义的参数。 这时,我们需要使用 add_rewrite_tag() 函数来告诉 WordPress,我们的参数是什么。

function add_product_rewrite_tags() {
  add_rewrite_tag( '%product%', '([^/]+)' ); // 定义 product 参数
  add_rewrite_tag( '%product_category%', '([^/]+)' ); // 定义 product_category 参数
}
add_action( 'init', 'add_product_rewrite_tags' );

代码解释:

  • add_rewrite_tag( '%product%', '([^/]+)' );
    • %product%:这是参数的名称,需要用百分号 % 包裹。
    • ([^/]+):这是一个正则表达式,用来匹配参数的值。 + 表示匹配一个或多个前面的字符。

使用 add_rewrite_tag() 之后,我们就可以使用 %product%%product_category% 在重写规则中使用这些参数了。

function add_product_rewrite_rules() {
  add_rewrite_rule(
    '^product/([^/]*)/([^/]*)/?',
    'index.php?product_category=$matches[1]&product=$matches[2]',
    'top'
  );
}
add_action( 'init', 'add_product_rewrite_rules' );

(注意:虽然我们添加了 rewrite tag,但是重写规则本身并没有改变。add_rewrite_tag 主要影响的是 WordPress 如何解析 URL 并填充 $wp_query 对象。 在大多数情况下,直接使用 $wp_query->query_vars 就可以正常工作,除非你遇到 WordPress 无法正确识别参数的情况。)

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

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

你可以通过以下代码来查看数据库中存储的重写规则:

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

重要提示:不要直接修改数据库中的重写规则!

虽然你可以直接修改数据库中的 rewrite_rules 选项,但是强烈不建议这样做! 因为 WordPress 会在刷新重写规则时覆盖你的修改。 你应该始终使用 add_rewrite_rule()remove_rewrite_rule() 等函数来管理重写规则。

常见问题与注意事项

  • 正则表达式错误: 正则表达式是 URL 重写的关键。 如果正则表达式写错了,重写规则就不会生效。 可以使用在线正则表达式测试工具来验证你的正则表达式是否正确。
  • 规则冲突: 如果多个重写规则匹配同一个 URL,WordPress 会使用第一个匹配的规则。 要注意规则的顺序,确保优先级高的规则放在前面。
  • 性能问题: 过多的重写规则会影响性能。 尽量减少重写规则的数量,并优化正则表达式的效率。
  • 服务器配置: URL 重写需要服务器支持。 如果你的服务器不支持 URL 重写,你需要配置服务器的 .htaccess 文件(对于 Apache 服务器)或 web.config 文件(对于 IIS 服务器)。

总结:URL 重写,让你的网站更上一层楼

add_rewrite_rule() 函数是 WordPress 提供的强大的工具,让我们能够自定义 URL 重写的规则,从而优化网站的 URL 结构,提升用户体验和 SEO 效果。 掌握了 URL 重写的技巧,你就能够在 WordPress 的世界里玩转 URL,打造出更酷炫、更高效的网站。

记住,正则表达式是关键,刷新重写规则是必须,不要直接修改数据库,有问题多查资料。 希望今天的讲座对你有所帮助!现在,拿起你的代码,开始创造属于你的酷炫 URL 吧!

发表回复

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