wordpress 里面内置了两种文章类型 Post Type ,为Post(文章)、Page(页面),分别用来展示两种类型的内容,一种是相对动态的文章,另一种是相对固定的页面。
但是极度开放包容的wordpress却并不甘于只做一个博客系统,越来越多的企业网站都用wordpress来搭建。那么单纯的文章种类,就不够用了。
这里就可以使用wordpress的文章类型功能新建一个产品类型,比如海天现在的培训机构需要使用wordpress搭建一个官网,需要课程、学员介绍的栏目,本文就以新建一个课程类型。
以下代码修改方法,适合那种自定义量少的,或者喜欢自己用代码的朋友使用。日常的推荐使用插件Pods,一键创建和修改自定义内容类型和字段内容,超级方便。
创建一个 post type
创建一个新的 Post Type 需要使用 register_post_type 函数来注册,在主题的 functions.php 文件下调用该函数:
register_post_type( $post_type, $args );
$post_type 参数为自定义 Post Type 的名称,Post Type 可以自定义的功能非常多,所以这个函数里面的 $args 参数会很多。所以通常会用下面这种格式来注册:
function my_custom_post_product() {
$args = array();
register_post_type( 'product', $args );
}
add_action( 'init', 'my_custom_post_product' );
包裹在一个函数中,定义一个数组,然后挂靠到 init 这个 action 上。这样 WordPress 在初始化的时候,就会执行这个函数注册一个自定义 Post Type,因为调用 register_post_type() 的时候,必须要在 admin_menu action 之前,在 after_setup_theme action 之后,所以这里最好挂靠到 init action 上。
参数很多,为了写教程方便,只列出比较常用的参数,大体结构如下:
function my_custom_post_course() {
$labels = array(
'name' => _x( 'Courses', 'post type 名称' ),
'singular_name' => _x( 'Course', 'post type 单个 item 时的名称,因为英文有复数' ),
'add_new' => _x( '新建课程', '添加新内容的链接名称' ),
'add_new_item' => __( '新建一个课程' ),
'edit_item' => __( '编辑课程' ),
'new_item' => __( '新课程' ),
'all_items' => __( '所有课程' ),
'view_item' => __( '查看课程' ),
'search_items' => __( '搜索课程' ),
'not_found' => __( '没有找到相关课程' ),
'not_found_in_trash' => __( '回收站里面没有相关课程' ),
'parent_item_colon' => '',
'menu_name' => '课程'
);
$args = array(
'labels' => $labels,
'description' => '空中英语online的课程信息',
'public' => true,
'menu_position' => 5,
'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt', 'comments' ),
'has_archive' => true
);
register_post_type( 'course', $args );
}
add_action( 'init', 'my_custom_post_course' );
保存functions.php文件后,刷新后台,就会发现后台新增了“课程”的类型栏目。
为 Post Type 添加分类功能
一个课程会有很多分类,比如少儿、青年等,那接下来就为课程的类型添加分类的功能。而添加分类功能需要使用函数 register_taxonomy,和注册 Post Type 函数差不多,直接给出参考代码:
function my_taxonomies_course() {
$labels = array(
'name' => _x( '课程分类', 'taxonomy 名称' ),
'singular_name' => _x( '课程分类', 'taxonomy 单数名称' ),
'search_items' => __( '搜索课程分类' ),
'all_items' => __( '所有课程分类' ),
'parent_item' => __( '该课程分类的上级分类' ),
'parent_item_colon' => __( '该课程分类的上级分类:' ),
'edit_item' => __( '编辑课程分类' ),
'update_item' => __( '更新课程分类' ),
'add_new_item' => __( '添加新的课程分类' ),
'new_item_name' => __( '新课程分类' ),
'menu_name' => __( '课程分类' ),
);
$args = array(
'labels' => $labels,
'hierarchical' => true,
);
register_taxonomy( 'course_category', 'course', $args );
}
add_action( 'init', 'my_taxonomies_course', 0 );
保存后,刷新wordpress后台就会看到课程分类的选项
为 Post Type 添加自定义 Meta Box
一个类型的内容会有很多参数,比如这里的课程内容,需要有年龄、上课时间等参数,那么就需要在编辑内容的时候添加自定义 Meta Box,Meta Box 可以在发表页面中添加自定义的表单,编辑的时候可以填写额外的信息方便在前端调用。
自定义 Meta Box 需要用到 add_meta_box 函数,和上面一样,还是直接给参考:
add_action( 'add_meta_boxes', 'course_year' );
function course_year() {
add_meta_box(
'course_year',
'课程年龄',
'course_year_meta_box',
'course',
'side',
'low'
);
}
然后在配置参数里面指定了回调函数 course_year_meta_box,我们需要在这个函数里面创建表单:
function course_year_meta_box($post) {
// 创建临时隐藏表单,为了安全
wp_nonce_field( 'course_year_meta_box', 'course_year_meta_box_nonce' );
// 获取之前存储的值
$value = get_post_meta( $post->ID, '_course_year', true );
?>
<label for="course_year"></label>
<input type="text" id="course_year" name="course_year" value="<?php echo esc_attr( $value ); ?>" placeholder="输入课程年龄" >
<?php
}
这时在编辑内容的时候,在侧栏就出现了课程年龄的meta box信息栏。
但这个时候提交之后并没有保存这个 Meta Box 的内容,还需要下面的验证保存内容的代码:
add_action( 'save_post', 'course_year_save_meta_box' );
function course_year_save_meta_box($post_id){
// 安全检查
// 检查是否发送了一次性隐藏表单内容(判断是否为第三者模拟提交)
if ( ! isset( $_POST['course_year_meta_box_nonce'] ) ) {
return;
}
// 判断隐藏表单的值与之前是否相同
if ( ! wp_verify_nonce( $_POST['course_year_meta_box_nonce'], 'course_year_meta_box' ) ) {
return;
}
// 判断该用户是否有权限
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
// 判断 Meta Box 是否为空
if ( ! isset( $_POST['course_year'] ) ) {
return;
}
$course_year = sanitize_text_field( $_POST['course_year'] );
update_post_meta( $post_id, '_course_year', $course_year );
}
为 Post Type 批量添加自定义 Meta Box
和添加单个Meta Box的原理是一样的,只是钩子调用的方法不同,给出相关代码方便使用,以为教师类型增加教龄和座右铭为例:
创建相关字段
$teacher_info=array(
"year" => array(
"name" => "year",
"std" => "",
"title" => "教龄"),
"content_2" => array(
"name" => "motto",
"std" => "",
"title" => "座右铭"),
);
创建字段输入框和模块
function new_meta_boxes() {
global $post, $teacher_info;
foreach($teacher_info as $meta_box) {
$meta_box_value = get_post_meta($post->ID, $meta_box['name'].'_value', true);
if($meta_box_value == "")
$meta_box_value = $meta_box['std'];
// 自定义字段标题
echo'<h3>'.$meta_box['title'].'</h3>';
// 自定义字段输入框
echo '<input type="text" name="'.$meta_box['name'].'_value" value="'.$meta_box_value.'" placeholder="'.$meta_box_value.'" >';
}
echo '<input type="hidden" name="teacher_metaboxes_nonce" id="teacher_metaboxes_nonce" value="'.wp_create_nonce( plugin_basename(__FILE__) ).'" />';
}
function create_meta_box() {
if ( function_exists('add_meta_box') ) {
add_meta_box( 'teacher-meta-boxes', '教师信息', 'new_meta_boxes', 'teacher', 'normal', 'high' );
}
}
保存字段数据
function save_postdata( $post_id ) {
global $teacher_info;
if ( !wp_verify_nonce( $_POST['teacher_metaboxes_nonce'], plugin_basename(__FILE__) ))
return;
if ( !current_user_can( 'edit_posts', $post_id ))
return;
foreach($teacher_info as $meta_box) {
$data = $_POST[$meta_box['name'].'_value'];
if($data == "")
delete_post_meta($post_id, $meta_box['name'].'_value', get_post_meta($post_id, $meta_box['name'].'_value', true));
else
update_post_meta($post_id, $meta_box['name'].'_value', $data);
}
}
最后,将函数连接到指定action(动作),以让WordPress程序执行上面的函数:
add_action('admin_menu', 'create_meta_box');
add_action('save_post', 'save_postdata');
为 Post Type 列表添加 Meta字段
有些重要的信息在内容列表里就能够显示,会大大的提高浏览内容的效率,比如说wordpress原生的文章列表里的tags,所以为新建的Post Type列表加上重要Meta字段。
使用函数manage_$post_type_posts_custom_column 实现:
add_action("manage_posts_custom_column", "course_custom_columns");
add_filter("manage_edit-course_columns", "course_edit_columns");
function course_custom_columns($column){
global $post;
switch ($column) {
case "course_year":
echo get_post_meta( $post->ID, '_course_year', true );
break;
}
}
function course_edit_columns($columns){
$columns['course_year'] = '年龄';
return $columns;
}
这样就在列表页面就增加了年龄的显示:
调用Post Type内容
自定义 Post Type 的模板
只需要创建 archive-[post_type].php 和 single-[post_type].php 就可以实现 Post Type 的列表访问和文章访问。
然后通过get_post_meta函数调用Meta Box信息,
get_post_meta( get_the_ID(), 'motto_value', true );
Post Type循环输出
在首页或者其他位置需要输出自定义Post Type的所有内容,使用以下代码配合上面的调用Meta Box信息方法调用:
$args = array( 'post_type' => 'product', 'posts_per_page' => 10 );
$loop = new WP_Query( $args );
while ( $loop->have_posts() ) : $loop->the_post();
the_title();
the_content();
echo get_post_meta( get_the_ID(), 'motto_value', true );
endwhile;
在首页列表的默认循环输出
自定义的 Post Type 的内容不会自动混入博客首页的主循环里面,需要使用 pre_get_posts 这个 action 来做处理。
add_action( 'pre_get_posts', 'add_my_post_types_to_query' );
function add_my_post_types_to_query( $query ) {
if ( is_home() && $query->is_main_query() )
$query->set( 'post_type', array( 'post', 'page', 'teacher' ) );
return $query;
}
在上面的 $query 变量里面设置的 post_type 数组就是要在主循环里面展示的内容,将自定义 Post Type 填写进去就可以在首页的循环中显示出来了。
[…] #Blog #Wordpress ✏️ 友链 WordPress 指北系列:wordpress的page页面内容调用wordpress自定义文章类型Post Type频道:@NewlearnerChannel 890 views初学者 | […]
[…] 之前海天在制作学校网站的时候,因为要涉及到不同类型的页面,所以需要创建不同页面类型和字段,当时是使用的纯代码次改function文件的方式来完成的(wordpress自定义文章类型Post Type)。一个两个的增加修改还好,但是如果需要增加的多了,那还是很麻烦的。 […]