How to register new post type with new taxonomy

这篇文章我将详细叙说如何在 WordPress 里运用 register_post_type 和 register_taxonomy添加新的文章类型和分类。

例如我们要新建一个文章类型叫 wine, 与之相对应的分类有两个,分别为  type, region。

所以我们大致需要这些数据,我把他们放到一个数组里:

$plugin_name = 'yaocms';
$portfolio_type = array(
    'type' => 'wine', //注册在数据库里的文章类型
    'name' => __('Wine', $plugin_name), //后台里显示菜单名称
    'singular' => __('Wine', $plugin_name), //单数形式
    'capability' => 'page', //兼容模式,page 或 post
    'supports' => array('title', 'editor', 'thumbnail', 'page-attributes'), //默认支持的字段,依次是:标题,主编辑区域,特色图片,排序
    'slug'     => 'wine-view', //显示在前端url里: https://yaoyingying.com/{$this slug}/文章名
    'taxonomy' => array( //分类学
            array(
                'name' => 'type', //注册到数据库的分类名
                'hierarchical' => true, //true 形式同 post 里的 分类,false 时候,形式同post 里的 tags。
                'label' => __('Type', $plugin_name), //后台显示的分类名的单数形式
                'labels' => __('Types', $plugin_name), // 复数形式
                'slug' => 'wine-type' //显示在前端该分类的 url 结构里: https://yaoyingying.com/{$this slug}/分类名
            ),
            array(
                'name' => 'region',
                'hierarchical' => true,
                'label' => __('Region', $plugin_name),
                'labels' => __('Regions', $plugin_name),
                'slug' => 'wine-region'
            ),
        )
    )
);

接下来,我们创建一个类(class)

class YaoCMS_Class {
    public $post_type;  //成员变量
    public function __construct() { //构造函数

     }
}
new YaoCMS_Class($portfolio_type);

现在需要一个方法让类获取到数组 $portfolio_type 里的内容。

    public function __construct($post_type = NULL) {
        if( isset($post_type) and !empty($post_type)){
              $this->setPostType($post_type);
        }
    }
    public function setPostType($post_type) {
        $this->post_type = $post_type;
    }

这样在构造函数里通过方法 setPostType 让成员变量 $post_type 获取到了外部数组 $portfolio_type 里的内容。

下面需要做的事就是根据 $post_type 里的内容来创建文章类型和分类:

    public function new_post_types() {
        register_post_type($this->post_type['type'], array( //创建新的文章类型
            'labels' => array(
                'name' => __($this->post_type['name'], self::LANG),
                'singular_name' => __($this->post_type['singular'], self::LANG),
                'menu_name' => __($this->post_type['name'], self::LANG)
            ),
            'public' => true,
            'publicly_queryable' => true,
            'show_ui' => true,
            'show_in_menu' => true,
            'query_var' => true,
            'rewrite' => array('slug' => $this->post_type['type']),
            'capability_type' => $this->post_type['capability'],
            'has_archive' => true,
            'hierarchical' => false,
            'menu_position' => null,
            'supports' => $this->post_type['supports']
        ));
        if ($this->post_type['taxonomy'] != '') { //如果有taxonomy,则创建文章分类
        	foreach ($this->post_type['taxonomy'] as $t) {
	            register_taxonomy($t['name'], $this->post_type['type'], array(
	                'hierarchical' => $t['hierarchical'],
	                'labels' => array(
	                    'name' => __($t['label'], self::LANG),
	                    'singular_name' => __($t['label'], self::LANG),
	                    'menu_name' => __($t['label'], self::LANG),
	                ),
	                'show_ui' => true,
	                'query_var' => true,
	                'rewrite' => array('slug' => $t['slug']),
	            ));
        	}

        }
    }

随后在构造函数里执行这个方法:

    public function __construct($post_type = NULL) {
        if( isset($post_type) and !empty($post_type)){
              $this->setPostType($post_type);
              add_action('init', array(&$this, 'new_post_types'));
         }      
    }

到现在为止,创建文章类型和分类的工作已经完成了,但是,他并没有完美,比如说,你发现左边菜单前面的菜单,别的都有个特别的图标,而你创建的,却很二。

好,我们可以依靠下面的方法,给你的文章类型一个特殊的图标:

    public function cpt_icons() {
        $posttype = $this->post_type['type'];
        $icon = plugins_url("/images/icons/" . $posttype . ".png", dirname(__FILE__)); //图标的地址
        echo <<<EOF
<style type="text/css" media="screen"> 
    #menu-posts-$posttype .wp-menu-image { background: url($icon) no-repeat 6px -17px !important; }    
    #menu-posts-$posttype:hover .wp-menu-image {  background-position:6px 7px!important; }
</style>
EOF;
    }

代码中 $icon 中便是一个小icon,通过下面的Css 将这个小图片放到背景里。

小图片必须按照下面的规范来制作,宽16px, 高 40px。

然后,同样的,需要到构造函数里执行这个方法

add_action('admin_head', array(&$this, 'cpt_icons'));

这还不够,或许你想将分类像所有文章页面那样显示在文章列表里,OK:

我们可以通过 add_filter,来添加分类栏到文章列表里。

    public function set_term_columns($columns){
    	unset( $columns['date'] );//注销日期栏
        foreach ($this->post_type['taxonomy'] as $t) {
	        	$tax[$t['name']] = $t['label'];
	    }
		return array_merge( $columns, $tax);
    }

在构造函数里执行 add_filter, 添加分类栏目

add_filter("manage_edit-" . $this->post_type['type'] . "_columns", array($this, 'set_term_columns'));

在通过下面的方法获取分类的值:

    public function term_column_values($column, $post_id) {
	        foreach ($this->post_type['taxonomy'] as $t) {
	            if($column == $t['name']){
	                $terms = get_the_term_list($post_id, $t['name'], '', ',', '');
	                if (is_string($terms)) {
	                    echo $terms;
	                } else {
	                    echo __('Null',self::LANG);
	                }
	        	}
		    }
    }

在构造函数里执行 add_action,添加分类栏目的值。

add_action("manage_" . $this->post_type['type'] . "_posts_custom_column", array($this, 'term_column_values'), 10, 2);

ok,这样分类栏目就添加到文章列表里了。

完整代码:https://github.com/yao3060/Yao-and-Wordpress/blob/master/classes/class-YaoCMS.php

其实可以通过 ‘show_admin_column’ => true, 来替换之前的方法将 taxonony 现实在post list 里