乌徒帮技术范儿WordPressWordPress开发 › register_post_type后的permalink固定链接和register_meta_box_cb问题

register_post_type后的permalink固定链接和register_meta_box_cb问题

分类:WordPress开发

在wordpress的开发中,偶尔会遇到一些特殊的发布类型需求,这些类型需要使用到新的post type,因此我们在开发中往往需要注意其中的一些问题,我发现的最大问题的就是在register_post_type后不能正常使用新的post type文章的固定链接,以及在添加新的meta_box时,不知道怎么使用register_meta_box_cb参数。因此在开发新的post_type之前你最好先阅读一下这篇文章,以防在开发过程中突然卡壳,浪费大量时间。

什么是post type?

post type是wordpress对内容文章的一种命名,即“文章类型”。它反映在数据库表中的_posts表中的post_type字段。文章类型目前知道有“post,page,attachment,revision,nav_menu_item”五种,而官方经常会用product和book来举例。post type和post format不同,虽然在后台,post format被翻译成文章形式,但实际上,它是一种分类形式,wordpress的分类形式可以在乌徒帮的中找到详细的说明。

但在wordpress中存在着对于中国用户非常不习惯的这种形式,WP的文章全部放在一个数据库表中,用post type来区别文章是什么类型。文章为什么要有类型呢?一般的文章(article)和独立页面(page)对于网站来说有不同的意义,独立页面是可以不需要分类(category)的,而文章是必须要有分类的。而且如果用过一些其他的系统就会发现,独立页面往往直接通过一个统一的URL去访问,而文章则常常和分类的URL联系在一起。

为什么要扩展文章分类?例如我想让一种文章专门用来发布产品,这类产品文章要分类,但需要一些特殊的属性,因此我可以建立一个product的post type来管理它们。

如何建立一种文章类型?使用register_post_type

这个函数不能直接使用在functions.php中,而是要通过add_action勾进wordpress的进程里。WP官方文档对register_post_type进行了降为详细的讲解,它的参数非常多,因此需要你特别注意。简单的用一个例子代码来说明问题吧:

function codex_custom_init() {
    $args = array( 'public' => true, 'label' => 'Books' );
    register_post_type( 'book', $args );
}
add_action( 'init', 'codex_custom_init' );

这样一来我们就生产出一种新的文章类型:book。而且你可以在query_posts(array('post_type'=>'book'))使用它。

我们的重点不在register_post_type,而是在创建新的文章类型之后的固定链接问题和添加新的meta_box问题上。

register_post_type后的permalink固定链接问题

在register_post_type参数中的label->slug和rewrite与新类型文章的访问URL有关,在rewrite为true不规定slug的情况下,将直接使用label->slug作为访问地址的前缀,如yourblog.com/book/red-and-black.html,其中的book即这个文章类型的前缀,book文章类型的所有文章访问时都需要通过这个前缀才能访问到。但在rerite->slug中我们可以跟换它为我们想要的前缀,如我们可以把book换为b。这个你可以阅读上面链接的官方文档中进行处理。但是问题是:

为什么我的book不能被这个网址正常的访问?!

[payfor price="2"]如果你第一次创建了一个新的文章类型,就会发现即使使用wordpress后台的“查看”链接,进入到的页面也无法正常访问到该book,而是显示404。问题产生的根源是:WP需要更新内部rewrite。wordpress的rewrite规则被记录在数据库表的_options表中,有兴趣你可以去看下。但是如果每次你希望通过创建程序来实现一些新的URL模式时,都会发现不能如愿。这是因为该表内的记录值没有被更新。你要做的就是更新以使它生效。方法由简及繁如下:

  1. 进入后台设置-固定链接,更新一下
  2. 如果更新后仍然不能访问,更换一种固定链接形式试试,一般来说使用/%postname%/比较有效
  3. 使用下面这段代码,它也有更新的效果
  4. 如果都不能解决的话,只能自己写.htaccess规则了
function my_project_rewrite_flush() {
    flush_rewrite_rules();
}
register_activation_hook(__FILE__,'my_project_rewrite_flush');

这段代码你最好仔细斟酌,因为它只适合用在插件中(register_activation_hook),如果你把它放在主题functions.php中,注意使用add_action('after_theme_setup','my_project_rewrite_flush');,如果after_theme_setup这个hook不行,你还需要试试其他的启动主题的hook,如after_switch_theme。[/payfor]

参考文献

register_meta_box_cb问题

在创建新的post type之后,你最想做的其实是为这种type增加新的meta_box功能,以让该类型的文章达到自己的创建目标。既然如此,你必然需要用到meta_box函数。在register_post_type中有个参数是register_meta_box_cb,但你会发现它完成不知道怎么去用。不用担心,在接下来的几段文字里你将非常了解它的用途。

首先,我们执行一个register_post_type,其中用到了register_meta_box_cb:

function codex_custom_init() {
    $args = array( 'public' => true, 'label' => 'Books','register_meta_box_cb' => 'my_book_field' );
    register_post_type( 'book', $args );
}
add_action( 'init', 'codex_custom_init' );

注意上面的'register_meta_box_cb' => 'my_book_field',这句话意思就是说要使用my_book_field()这个函数作为meta_box勾入函数。在官方文档中说的很清楚,要使用add_meta_box来实现meta_box的添加。

function my_book_field(){
	add_meta_box(
		'my_book_field', // 这个随便填写,只是一个ID号
		'书本信息', // 这个作为meta box的标题,并且也显示在标题处
		'book_inner_custom_box', // 这个是一个函数的名称,它将执行真正的meta box,并把它打印出来
		'book' // post type的别名
	);
}

那么这样一个meta_box信息就注册好了,接下来就是设计一个自己的meta_box

function book_inner_custom_box(){
// 这里编辑任何你需要显示在后台的内容,例如一些要发布的信息的input textarea等
}

如何要提交这些信息,可以使用一个钩子钩在发布文章的时候。

add_action('save_post', 'save_book_meta', 1, 2);
function save_book_meta($post_id,$post){
// 这里打你需要进行数据处理的代码
}

这样一个post type的register_meta_box_cb问题就解决了。

参考文献:1 2

等等,看上去如此简单啊!是的,这个思路流程是非常简单的,但是如果你以前用过这段代码的话,或许就会晕掉了。即在上面的my_book_field()边上使用一个

add_action('add_meta_boxes','my_book_field');

如果你还记得起来的话,这就非常令人诧异了,因为在我们上述的程序中,没有用到它,而后台已经可以正常使用meta box了。这其实是因为:register_meta_box_cb这个参数其实等效于这个add_action

还有一个问题是,有些数据其实你并不想在save_post的时候才去处理,而是想在之前就处理好。那么你可以把这些处理代码放在my_book_field()中,因为它被狠狠的勾在meta box要出现的页面,因此也就是这个页面的处理函数。如果你想提前预备好一些数据,完全可以在这个函数中事先计算好。

已有1条评论 快速评论
  1. […] 在我们之前的文章《register_post_type后的permalink固定链接和register_meta_box_cb问题》中,我们已经提到过新的post_type注册后链接不能访问的处理办法。但post_type文章的固定链接形式其实只能是/post_type/post_name的形式,而不能成为post_type/post_id形式,可是我们常常希望某种特殊文章只用post_id来作为访问地址,例如产品、书籍等。 […]

填写个人信息,赶快回复吧!