阐述 `WP_Rewrite` 类的源码,它是如何存储和管理 URL 重写规则的?

各位观众,大家好!今天咱们来聊聊 WordPress 里面一个挺神秘,但又非常重要的家伙—— WP_Rewrite 类。说它神秘,是因为很多人用了 WordPress 很久,都没直接跟它打过交道。说它重要,是因为它负责管理 WordPress 的 URL 重写规则,也就是让你的网站链接看起来更漂亮、更 SEO 友好。

一、WP_Rewrite 类:URL 重写的幕后英雄

想象一下,没有 WP_Rewrite,你的文章链接可能长这样:/?p=123。这玩意儿机器能看懂,但人看着就觉得…嗯…不够优雅。有了 WP_Rewrite,你可以把链接变成这样:/my-awesome-article/,是不是瞬间高大上了?

WP_Rewrite 类的主要作用就是:

  1. 定义重写规则: 它存储了一系列规则,告诉 WordPress 如何把丑陋的内部 URL 转换成漂亮的外部 URL。
  2. 解析 URL: 当用户访问一个漂亮的 URL 时,它会解析这个 URL,找到对应的 WordPress 内容。
  3. 生成 URL: 在 WordPress 生成链接时,它会根据规则生成对应的漂亮 URL。

二、WP_Rewrite 的核心属性:规则在哪里?

WP_Rewrite 类有很多属性,但最核心的几个是:

  • $rewritecode:这是一个数组,存储了用于替换的标签。比如 %postname%%category% 等。
  • $rewritereplace:这是一个数组,存储了与 $rewritecode 对应的替换值。
  • $rules:这是一个关键数组,存储了最终的重写规则。每个规则都是一个键值对,键是正则表达式(用于匹配 URL),值是查询字符串(告诉 WordPress 要加载什么内容)。
  • $permalink_structure:存储了永久链接的结构。比如 /blog/%postname%/
  • $endpoints:存储了额外的 URL 终结点,比如 feedtrackbackcomments 等。

这些属性都是 protected 级别的,意味着你不能直接从类的外部访问它们。你需要通过类提供的方法来操作这些属性。

三、WP_Rewrite 的核心方法:规则如何生效?

接下来,咱们来看看 WP_Rewrite 类的一些核心方法:

  1. __construct() 构造函数,负责初始化各种属性,并加载现有的重写规则。

    public function __construct() {
        // 初始化
        $this->rewritecode = array('%year%', '%monthnum%', '%day%', '%hour%', '%minute%', '%second%', '%postname%', '%post_id%', '%category%', '%tag%', '%author%', '%pagename%', '%search%', '%feed%', '%comment_feed%', '%trackback%', '%author_name%', '%category_name%', '%tag_id%', '%category_nicename%', '%tag_slug%', '%year%/%monthnum%', '%postname%/', '%post_id%/', '%page%');
        $this->rewritereplace = array('([0-9]{4})', '([0-9]{1,2})', '([0-9]{1,2})', '([0-9]{1,2})', '([0-9]{1,2})', '([0-9]{1,2})', '([^/]+)', '([0-9]+)', '([^/]+)', '([^/]+)', '([^/]+)', '([^/]+)', '(.+)', '(feed|rdf|rss|rss2|atom)', '(feed|rdf|rss|rss2|atom)', '(trackback)', '([^/]+)', '([^/]+)', '([0-9]+)', '([^/]+)', '([^/]+)', '([0-9]{4})/([0-9]{1,2})', '([^/]+)/', '([0-9]+)/', '([0-9]+)');
    
        // 加载已有的重写规则
        $this->rules = (array) get_option('rewrite_rules');
    
        // 其他初始化代码...
    }
  2. wp_rewrite_rules() 这个方法是 WordPress 加载重写规则的关键。它会调用 WP_Rewrite 实例的 wp_rewrite_rules() 方法,从而将规则添加到 WordPress 的 URL 解析过程中。

    function wp_rewrite_rules() {
        global $wp_rewrite;
    
        if ( ! isset( $wp_rewrite ) ) {
            $wp_rewrite = new WP_Rewrite();
        }
    
        return $wp_rewrite->wp_rewrite_rules();
    }
  3. wp_rewrite_rules() (WP_Rewrite 类中的版本): 这个方法才是真正干活的。它会根据当前的永久链接结构和其它设置,生成一系列重写规则,并将它们存储到 $rules 属性中。

    public function wp_rewrite_rules() {
        //  省略大量代码...
        //  这里会根据permalink_structure, category_base, tag_base等生成规则
        //  例如:
        //  'blog/([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/([^/]+)/?$' => 'index.php?year=$1&monthnum=$2&day=$3&name=$4'
        //  省略大量代码...
    
        return $this->rules;
    }
  4. generate_rewrite_rules() 这个方法根据给定的参数(比如文章的链接结构、分类的链接结构等),生成相应的重写规则。

    public function generate_rewrite_rules( $permalink_structure, $ep_mask, $paged = true, $feed = true, $forcomments = false, $walk_dirs = true, $endpoints = true ) {
        // 省略大量代码...
        // 根据传入的参数,生成各种重写规则
        // 省略大量代码...
    
        return $rewrite_rules;
    }
  5. rewrite_rules() 这个方法返回 $rules 属性,也就是存储重写规则的数组。

    public function rewrite_rules() {
        return $this->rules;
    }
  6. flush_rules() 这个方法用于刷新重写规则。当你修改了永久链接结构或者其它与 URL 重写相关的设置时,你需要调用这个方法来更新重写规则。它会先删除旧的规则,然后重新生成新的规则,并将它们保存到数据库中。这个函数非常重要,因为如果你不刷新规则,你的新链接结构可能无法正常工作。

    public function flush_rules( $hard = true ) {
        global $wpdb;
    
        if ( ! is_network_admin() && ! is_super_admin() && current_filter() !== 'wp_loaded' ) {
            /** This action is documented in wp-includes/rewrite.php */
            do_action( 'flush_rewrite_rules', $hard );
            return;
        }
    
        /** This action is documented in wp-includes/rewrite.php */
        do_action( 'flush_rewrite_rules', $hard );
    
        if ( $hard ) {
            $this->init();
    
            // Remove rules.
            delete_option( 'rewrite_rules' );
    
            $this->wp_rewrite_rules();
            $this->add_rewrite_rules();
            $this->rewrite_rules_filter();
    
            // Update rules.
            update_option( 'rewrite_rules', $this->rules );
    
            // Update the .htaccess file.
            $this->mod_rewrite_rules();
    
            // Flush rules is sometimes called from plugins/themes
            // during admin screens.  Prevent redirect loops.
            if ( ! is_admin() ) {
                redirect_guess_404_permalink();
            }
        } else {
            $this->add_rewrite_rules();
            $this->rewrite_rules_filter();
            update_option( 'rewrite_rules', $this->rules );
        }
    }
  7. add_rule() 这个方法用于添加自定义的重写规则。你可以使用它来创建自己的 URL 结构。

    public function add_rule( $regex, $redirect, $after = 'bottom' ) {
        if ( 'bottom' === $after ) {
            $this->rules[ $regex ] = $redirect;
        } else {
            $new_rules = array( $regex => $redirect );
            $this->rules = $new_rules + $this->rules;
        }
    }

四、WP_Rewrite 的工作流程:从 URL 到内容

当用户访问你的 WordPress 网站时,WP_Rewrite 类会参与到 URL 解析的过程中。具体流程如下:

  1. 用户访问 URL: 用户在浏览器中输入一个 URL,比如 /my-awesome-article/
  2. WordPress 接收请求: WordPress 接收到用户的请求。
  3. WP_Rewrite 解析 URL: WP_Rewrite 类会遍历 $rules 数组中的正则表达式,尝试匹配用户访问的 URL。
  4. 找到匹配的规则: 如果找到了匹配的规则,WP_Rewrite 类会提取出正则表达式中的参数。
  5. 生成查询字符串: WP_Rewrite 类会根据匹配的规则和提取出的参数,生成一个查询字符串,比如 index.php?name=my-awesome-article
  6. WordPress 加载内容: WordPress 会根据查询字符串,加载对应的内容(比如文章、页面等)。
  7. 返回响应: WordPress 将加载的内容返回给用户。

五、WP_Rewrite 的实际应用:修改永久链接结构

最常见的 WP_Rewrite 应用场景就是修改 WordPress 的永久链接结构。你可以在 WordPress 后台的“设置”->“固定链接”页面中选择不同的永久链接结构。

当你选择了一个新的永久链接结构后,WordPress 会自动调用 WP_Rewrite 类的 flush_rules() 方法来刷新重写规则。

六、WP_Rewrite 的高级用法:自定义重写规则

除了修改永久链接结构,你还可以使用 WP_Rewrite 类来创建自己的重写规则。这可以让你实现一些更高级的 URL 结构。

比如,你可以创建一个规则,将 /products/iphone/ 转换成 index.php?product=iphone

add_action( 'init', 'my_custom_rewrite_rules' );

function my_custom_rewrite_rules() {
    global $wp_rewrite;

    // 添加重写规则
    $wp_rewrite->add_rule(
        'products/([^/]+)/?',
        'index.php?product=$matches[1]',
        'top'
    );

    // 刷新重写规则 (注意: 仅在第一次添加规则时需要)
    $wp_rewrite->flush_rules();
}

add_filter( 'query_vars', 'my_custom_query_vars' );

function my_custom_query_vars( $query_vars ) {
    // 添加 query variable
    $query_vars[] = 'product';
    return $query_vars;
}

这段代码做了以下几件事:

  1. add_action( 'init', 'my_custom_rewrite_rules' ) 在 WordPress 初始化时,执行 my_custom_rewrite_rules() 函数。
  2. my_custom_rewrite_rules() 这个函数负责添加自定义的重写规则。
    • $wp_rewrite->add_rule( 'products/([^/]+)/?', 'index.php?product=$matches[1]', 'top' ): 添加一个重写规则,将 products/iphone/ 转换成 index.php?product=iphone
    • $wp_rewrite->flush_rules(): 刷新重写规则。注意: 刷新重写规则是一个耗时的操作,所以只需要在第一次添加规则时执行一次。
  3. add_filter( 'query_vars', 'my_custom_query_vars' ) 在 WordPress 查询变量被过滤时,执行 my_custom_query_vars() 函数。
  4. my_custom_query_vars() 这个函数负责添加自定义的查询变量。
    • $query_vars[] = 'product': 添加一个名为 product 的查询变量。

七、WP_Rewrite 的注意事项:坑在哪里?

在使用 WP_Rewrite 类时,需要注意以下几点:

  • 刷新重写规则: 当你修改了永久链接结构或者添加了自定义的重写规则后,一定要刷新重写规则。否则,你的修改可能不会生效。
  • 正则表达式: 重写规则中的正则表达式需要写正确。否则,你的规则可能无法匹配到正确的 URL。
  • 查询变量: 如果你在重写规则中使用了自定义的查询变量,你需要将这些变量添加到 WordPress 的查询变量列表中。
  • 性能: 过多的重写规则会影响网站的性能。所以,尽量只添加必要的规则。

八、WP_Rewrite 的调试技巧:如何排查问题?

当你的重写规则没有生效时,你可以使用以下技巧来调试问题:

  • 检查 .htaccess 文件: 如果你的服务器支持 .htaccess 文件,你可以检查这个文件是否包含了正确的重写规则。
  • 使用 var_dump()print_r() 你可以使用 var_dump()print_r() 函数来输出 $wp_rewrite->rules 数组,查看是否包含了你添加的规则。
  • 使用插件: 有一些 WordPress 插件可以帮助你调试重写规则。

九、总结:WP_Rewrite 的价值

WP_Rewrite 类是 WordPress 中一个非常重要的组件。它负责管理 URL 重写规则,让你的网站链接更漂亮、更 SEO 友好。通过理解 WP_Rewrite 类的工作原理,你可以更好地控制 WordPress 的 URL 结构,从而提升网站的用户体验和搜索引擎排名。

特性 描述
URL 美化 将丑陋的 URL (例如 /?p=123) 转换为更具可读性和 SEO 友好的 URL (例如 /my-awesome-article/)。
规则存储 使用 $rules 数组存储重写规则,其中键是正则表达式,值是查询字符串。
规则生成 使用 generate_rewrite_rules() 方法根据永久链接结构和其他设置生成规则。
规则刷新 使用 flush_rules() 方法刷新重写规则,这在修改永久链接结构或添加自定义规则后是必要的。
自定义规则 使用 add_rule() 方法添加自定义重写规则,允许创建符合特定需求的 URL 结构。
URL 解析 当用户访问一个 URL 时,WP_Rewrite 会解析该 URL,并将其转换为 WordPress 可以理解的查询字符串。
性能考虑 过多的重写规则会影响网站性能,因此应谨慎添加规则。
调试技巧 可以检查 .htaccess 文件、输出 $wp_rewrite->rules 数组或使用插件来调试重写规则。
核心方法 __construct(), wp_rewrite_rules(), generate_rewrite_rules(), rewrite_rules(), flush_rules(), add_rule() 等。
核心属性 $rewritecode, $rewritereplace, $rules, $permalink_structure, $endpoints 等。

希望今天的讲座对大家有所帮助!如果大家有什么问题,欢迎提问。下次再见!

发表回复

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