WordPress 应用中如何实现 URL 内部重定向

这里要说的 URL 重定向不是指地址栏输入一个 url a,然后地址栏的 url a 被变为 url b 那样的重定向,而是指 url 不变的重定向,也就是重定向过程在服务端默默的帮你完成了。


这个需求是源于开发 WordPress 插件时,然望在前端仅用 http://unmi/dosth 这种形式来访问自己的插件程序,而不是用 http:/unmi/wp-content/my-wordpress-plugin/dosth.php 这么一长串不友好的 URL。

有三种办法:

1. WordPress 是极力推荐与 Apache 搭配使用,所以可以在 Apache 的配置文件中用 Alias 指令。其实一开始我是想在应用的 .htaccess 文件中加指令,使用 mod_rewrite 模块来实现 URL 内部重定向功能,但碰到一些问题,所以暂时先在 httpd.conf 中加过 Alias 指定别名来实现过:

Alias "/do-subscribe" "C:\xampp\htdocs\unmi_site\wp-content\plugins\my-wordpress-plugin\do-subscribe.php"

这样在地址栏中用 http://unmi/do-subscribe 就能访问到原本用 http://unmi/wp-content/plugins/my-wordpress-plugin/do-subscribe.php 来访问的内容,且地址栏中的 URL 是保持不变的。不好的一点是被访问的程序页面要用它在文件系统中的绝对路径。

2. 在应用的 .htaccess 文件中加重写指令

WordPress 的永久链接功能会帮我们把 URL 处理成友好的形式,实现的办法是在应用的根目录下生成一个 .htaccess 文件,内容如下:
 1# BEGIN WordPress
 2<IfModule mod_rewrite.c>
 3RewriteEngine On
 4RewriteBase /
 5RewriteCond %{REQUEST_FILENAME} !-f
 6RewriteCond %{REQUEST_FILENAME} !-d
 7RewriteRule . /index.php [L]
 8</IfModule>
 9
10# END WordPress
对于一个自己的 Apache 应用,我在 .htaccess 文件中加上
1RewriteEngine On
2RewriteRule /do-subscribe wp-content/plugins/fn-subscription/do-subscribe.php
就能用 http://unmi/do-subscribe 访问到 http://unmi/wp-content/plugins/my-wordpress-plugin/do-subscribe.php 的内容,所以我也在 WordPress 应用的 .htaccess 文件中的 </IfModule> 之前加

RewriteRule /do-subscribe wp-content/plugins/fn-subscription/do-subscribe.php

可以怎么都不启作用,http://unmi/do-subscribe 总是提示 404 错误,所以才有过在 httpd.conf 中用 Alias 指令的做法。后来随着进一步研究 WordPress 的 PermaLinks 的实现才知道,必须把自己的 URL 重写规则写在 RewriteCond 之前才能由 Apache 优先处理,.htaccess 文件的内容写成:
1# BEGIN WordPress
2<IfModule mod_rewrite.c>
3RewriteEngine On
4RewriteBase /
5RewriteRule do-subscribe wp-content/plugins/fn-subscription/do-subscribe.php
6RewriteCond %{REQUEST_FILENAME} !-f
7RewriteCond %{REQUEST_FILENAME} !-d
8RewriteRule . /index.php [L]
9</IfModule>
因为有了 RewriteBase /,所以不用写成 RewriteRule /do-subscribe 的,斜杠省去了。用 http://unmi/do-subscribe 就能访问到你要的内容了,注意到这里被转向的页面用相对路径就 OK。

3. 前面讲的方法都是要改配置文件,可能你没有权限去改 Apache 的 httpd.conf 文件,或许改 .htacess 起来也麻烦,你完全可以在自己的插件中实现 URL 内部重定向的功能。

前面提过 WordPress 的 PermaLinks 实现了 URL 友好化重定向的功能,我们可以让自己的 URL 重写规则优先于 PermaLinks 被处理,可以在我们的插件里写上这样的代码:
 1<?php
 2/**
 3 * Define url rewrite rules class
 4 * Save as file include/url_rewrite_rules.php
 5 */
 6class UrlRewriteRules {
 7
 8    //define url rewrite rules
 9    //这里用关联数组来定义自己的一个个 URL 重写规则
10    private static  $redirects = array(
11        '/do-subscribe'=>'wp-content/plugins/my-wordpress-plugin/do-subscribe.php',
12        '/doremi' => 'wp-content/plugins/my-wordpress-plugin/doremi.php'
13    );
14
15    public static function get_redirects(){
16        return UrlRewriteRules::$redirects;
17    }
18
19    //处理 URL 重写规则,注意 $dest 中使用全局变量时必须先用 global $g 先引入
20    function redirect(){
21        // this is what the user asked for
22        $userrequest = str_replace(get_option('home'),'',$this->getAddress());
23
24        $userrequest= preg_replace("/\?.+/", '', $userrequest);
25        $userrequest = rtrim($userrequest,'/');
26
27        foreach (UrlRewriteRules::$redirects as $url => $dest) {
28            if($userrequest == rtrim($rule['url'],'/')) {
29
30                //note: global variables in these included files must use
31                //global $var to introduct
32                //把目标程序的代码引入到这里来,所以 URL 地址是不会变的
33                //这样的话,$dest 中的代码是在函数 redirect 中执行的
34                //所以在 $dest 中使用全局变量时必须先用 global $g 先引入
35                include_once(ABSPATH.$dest);
36                exit();
37            }
38        }
39    } // end funcion redirect
40
41    /*
42     * utility function to get the full address of the current request
43     * credit: http://www.phpro.org/examples/Get-Full-URL.html
44     */
45     function getAddress(){
46         /*** check for https ***/
47         $protocol = $_SERVER['HTTPS'] == 'on' ? 'https' : 'http';
48         /*** return the full address ***/
49          return $protocol.'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
50     }
51} // end  UrlRewriteRules class
52
53//--------------------------------------------------------------//
54
55//add custom url rewrite rules to the wordpress
56//include file url_rewrite_rules.php first
57require_once('include/url_rewrite_rules.php');
58$url_rewrite_rules = new UrlRewriteRules();
59
60if (isset($custom_url_rewriter)) {
61    // add the redirect action, high priority
62    //注册我们自己的 URL 重写规则,优先级设置高一些
63    add_action('init', array($url_rewrite_rules,'redirect'), 1);
64}

上面因为 redirect 方法是定义在 UrlRewriteRules 类中,所以必须写成 add_action('init', array($url_rewrite_rules,'redirect'), 1); 来注册初始化插件。如果直接定义成的一个全局函数则只要写成 add_action('init', 'redirect', 1) 就行。

好了,不用改动任何的配置文件,完全在自己的插件中定义 URL 内部重定向规则,减少了污染。我们可用简单 http://unmi/doremi 来访问了,借助于 option 的操作,可以做一个随意定制 URL 重写规则的插件了。

参考:1. WordPress Rewrite / Permalink内部过程分析[转]

又发现一款能满足此地要求的插件,GoCodes,具体介绍看这个:实现网站地址URL重新转向的WordPress插件:GoCodes, 我都觉得十分有必要用这个了。 永久链接 https://yanbin.blog/wordpress-custom-url-redirection/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。