WordPress的post、tag、category固定链接都可以在后台更改,唯独page不可以,page的默认SEO URL格式就是/%pagename%,结尾是否有反斜杠取决于设置的固定连接格式结尾是否有反斜杠。今天在WP Force看到修改page固定连接的方式,很激动,赶快记录下来。

修改page固定链接格式

假设一个页面的链接格式为

http://www.solagirl.net/guestbook

想改成

http://www.solagirl.net/page/guestbook.html

也就是加一个前缀page,再加一个后缀.html

将下面的代码放到functions.php中就可以实现

add_action( 'init', 'custom_page_rules' );
 
function custom_page_rules() {
    global $wp_rewrite;
    $wp_rewrite->page_structure = $wp_rewrite->root . 'page/%pagename%.html';
}

保存后记得到后台->设置->固定链接中重新保存一下固定链接格式,更新rewrite rule,这样才能生效,否则就是404。

但有一个小问题。。。

Canonical URL带来的问题

注意下面两种固定连接格式,是有很大区别的

结尾有反斜杠
结尾有反斜杠

结尾没有反斜杠
结尾没有反斜杠

假如你使用第一种设置,那么

http://www.solagirl.net/guestbook

会自动被重定向到

http://www.solagirl.net/guestbook/

当你给page固定链接添加后缀时,会造成

http://www.solagirl.net/page/guestbook.html

被重定向到

http://www.solagirl.net/page/guestbook.html/

一个小小的反斜杠足以让你美梦破碎。这个反斜杠为什么会出现?因为WordPress有一个Canonical URL功能,也就是避免重复,当有多个地址指向同一个页面时,在WordPress看来只有一个是正确的,不正确的要被定向到正确的地址,这样对搜索引擎很友好。只是凡事都有个例外,我们要给page设定后缀,这个功能就不友好了。

那么就禁用这个功能,不可完全禁用,只是显示page时禁用。禁用的方法在function redirect_canonical()中有写,这个函数实在太长了,没有读下去的勇气,不过开发团队写了一句救命的注释。

// Note that you can use the "redirect_canonical" filter to 
//cancel a canonical redirect for whatever reason by returning false
$redirect_url = apply_filters('redirect_canonical', $redirect_url, $requested_url);

这样我们在page页面禁用Canonical url的代码如下

add_filter('redirect_canonical', 'cancel_redirect_canonical');
      
function cancel_redirect_canonical($redirect_url)
{
    if( is_page()) return false;
    return $redirect_url;
}

 

实现修改page固定连接格式的完整代码如下

add_action( 'init', 'custom_page_rules' ); 
function custom_page_rules() {
    global $wp_rewrite;
    $wp_rewrite->page_structure = $wp_rewrite->root . 'page/%pagename%.html';
}

add_filter('redirect_canonical', 'cancel_redirect_canonical');    
function cancel_redirect_canonical($redirect_url)
{
    if( is_page()) return false;
    return $redirect_url;
}

写在functions.php中可以用,但这种与主题关系不大的功能还是写成插件更合适。

记得在文章《如何修改自定义文章类型的固定链接》中和tiger同学讨论过为何将custom post type的链接格式改为后面带反斜杠的就搞出404错误,原来是WordPress自动更正URL的功能在搞怪。

参考文章

介绍修改page固定链接格式

How to Change the WordPress Default Permalinks for Pages

告诉我结尾反斜杠和恼人的重定向是咋回事的文章

Remove Trailing Slash for Permalinks with Extensions

19条留言

  1. 比较关心怎么在文章页面加前缀post,再加一个后缀.html

  2. 楼主使用你这种方法有个致命的缺点,自定义文章回复评论后提交,出现404错误,麻烦看看啊

    1. 是有这问题,但这功能有很多插件可以实现,所以不打算更新代码,这文章很老了

  3. 博主好!我还想请教一件事,虽然跟文章内容无关,不好意思了。
    我最近在做一个自定义文章类型。现在single-event.php里有一个固定的div,并且div里有个图片。我想用catch_first_image() 类似的函数把第一张图片读取到首页(archive-event.php)。现在问题是, 这图片并不在内容区(the_content())里,而在文章内容之外。我搜了很多内容,就找不到了如何获取文章内容之外的第一个图片的文章了。有没更好的办法弄这个?

    1. 现在single-event.php里有一个固定的div,并且div里有个图片

      请问你是要获取这个div的图片吗?文章内容之外的图片是不是指这个?这个图片是怎么产生的?知道是怎么产生的应该可以获取

      1. 是的,这个div里面图片,而这图片不是由WP的函数来生成,图片是视频缩略图。 我的方法是这样的。
        我给某个自定义字段内直接贴出视频地址,然后用下面的通用函数库
        http://www.hdj.me/demos/vediourlparser/
        把视频缩略图输出到我上面说的那个div里(因为不能输出到the_content()里),现在我想首页显示这个div里的图,可是因为图没在the_content里输出,不能用firs image之类的函数获取文章内容里的第一张图。明白我的意思吗?

        1. 如果你已经把获取的缩略图地址存储到自定义字段里,那可以直接读取这个字段获取图片啊,循环输出时是可以知道post_id的。

          $url = get_post_meta($post_id, '你自定义字段的名字'true);

          不知道我理解的对不对,如果你没有保存这个数据到数据库,就得用别的方法

           

          1. 我承认我很傻,因为这几天熬夜弄这些,看来已经傻到已经程度了。
            我跟你说的那个div里的图片就是用上面你写的那段代码来实现的,只是我对自定义字段的了解还不够深刻,还以为自定义字段的代码只能在single.php里才可以调用。现在问题解决了,嗨,惭愧惭愧!

          2. 对了,方便的话留下IM或者邮箱可以吗?这样每次来你博客写跟文章无关的东西我也很惭愧。再次谢谢你了

          3. 你用的qq邮箱是你常用qq吗,是的话我加你qq

          4. 是的,可以加那个

  4. 这个方法我确实需要,现在我把代码复制到function.php里成功了,可是每个页面都在page/xxx.html 形式出来,比如留言板也page/guestbook.html这样了。我只需要把某一个页面弄成这样的。现在我把
    $wp_rewrite->page_structure = $wp_rewrite->root . ‘page/%pagename%.html’;
    这行里的代码改成
    $wp_rewrite->page_structure = $wp_rewrite->root . ‘movie/%pagename%.html’;
    这样了,但出现了404。
    还有我上面说的那样,我想除了这个页面,其他的都按原来的固定连接形式出来,如何过滤其他页面呢?我把
    if( is_page(‘sample-page’))
    这个改了,但还是没成功

    1. 这段代码实现不了你说的,如果你想每个页面的地址可以随意定制,建议你安装插件Custom Permalinks,这个插件你允许在编辑页面界面直接更改固定链接,每个页面都可以自定义,很方便。

      如果你不想用插件,而且只想改一个页面的地址,那可以用下面的代码

      class My_Page_Structure { 
      	public $page_id;
      	public $page_structure;
        
          function __construct( $page_id, $page_structure ) {
      		$this->page_id = $page_id;
      		$this->page_structure = $page_structure;
      		add_filter('page_link', array(&$this,'custom_book_link'), 10, 2);
      		add_action( 'init', array(&$this,'custom_book_rewrites_init') );
      		add_filter('redirect_canonical', array(&$this,'cancel_redirect_canonical') );
      	}
      
        
      	function custom_book_link( $permalink, $post ){
      		
      		if ( $post == $this->page_id ) {
      			return get_home_url(). '/' . $this->page_structure;
      		}	
      		return $permalink;
      	} 
      	  
      	function custom_book_rewrites_init(){
      		add_rewrite_rule(
      			$this->page_structure.'$',
      			'index.php?page_id='.$this->page_id,
      			'top' );
      	}
      		  
      	function cancel_redirect_canonical($redirect_url)
      	{
      		if( is_page($this->page_id) ) return false;
      	}
      }
      
      $mypage_structure = new My_Page_Structure( 1237, 'movie/sample-page.html');

      最后一句话中

      $mypage_structure = new My_Page_Structure( 1237, 'movie/sample-page.html');

      1237是你想改地址的页面的ID,movie/sample-page.html是这个页面的固定链接地址。这里直接硬编码了,否则你得查询数据库,获取page slug。

      最后一点,每次更改这个函数后,都要到设置->固定链接中重新保存一下固定链接,更改才能生效。

    1. 只是介绍了一种方法,就跟后台设置post固定链接一样,不存在网站固定下来要不要改链接的问题。即使改固定连接格式,只要做好301重定向也不会对SEO有负面影响。

评论功能已关闭