本文是《实例讲解 WordPress 自定义文章类型》专题的第 2 篇,共 2 篇:
- WordPress 自定义文章类型 介绍及实例解说(上)
- WordPress 自定义文章类型 介绍及实例解说(下)
在上篇《WordPress 自定义文章类型 介绍及实例解说(上)》,我们已经介绍了如何创建自定义文章类型,接下来将更进一步地解说 自定义文章类型 这个强大的WordPress功能。
请下载本文演示的文件:https://static.wpdaxue.com/img/2013/03/Movie-Reviews.1.zip
本好代码教程将介绍如何为自定义文章类型创建自定义分类法(custom taxonomies)、管理列(admin columns)、过滤器(taxonomy filters)和存档页(archive page)。让我们开始吧!
自定义文章类型的自定义分类法(Custom Taxonomy for Custom Post Types)
分类对于我们归类和查找文章都十分有用。在 WordPress 中,我们通常使用 分类(Categories)和标签(Tags)作为分类方法。下面将介绍如何一步步为你的自定义文章类型创建自定义分类法。
步骤1:注册自定义函数
打开上一篇文章中创建的插件,打开例子中的 Movie-Reviews.php ,将下面的代码添加到 最后一个 ?> 的前面:
1 | add_action( 'init', 'create_my_taxonomies', 0 ); |
add_action( 'init', 'create_my_taxonomies', 0 );
步骤2:完善自定义功能和注册自定义分类法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | function create_my_taxonomies() { register_taxonomy( 'movie_reviews_movie_genre', 'movie_reviews', array( 'labels' => array( 'name' => 'Movie Genre', 'add_new_item' => 'Add New Movie Genre', 'new_item_name' => "New Movie Type Genre" ), 'show_ui' => true, 'show_tagcloud' => false, 'hierarchical' => true ) ); } |
function create_my_taxonomies() { register_taxonomy( 'movie_reviews_movie_genre', 'movie_reviews', array( 'labels' => array( 'name' => 'Movie Genre', 'add_new_item' => 'Add New Movie Genre', 'new_item_name' => "New Movie Type Genre" ), 'show_ui' => true, 'show_tagcloud' => false, 'hierarchical' => true ) ); }
在这里, register_taxonomy 函数为“movie_reviews”这个自定义文章类型创建了一个名为 “movie_reviews_movie_genre”的 自定义分类法【在这个例子中,是一个分类(in our case a category)】。标签定义的分类管理部分使用不同的字符串。
'show_ui' => true
用于在仪表盘中,使分类编辑器可见。'show_tagcloud' => false
控制是否显示标签云。在我们的例子中,它是禁用的。'hierarchical' => true
控制自定义分类法的格式。
提示:
'hierarchical' => false
是指将分类(categories)转化成标签(tags)。
步骤3:显示自定义分类法
保存 Movie-Reviews.php 文件后,打开我们的自定义模板文件,也即是我们例子中的 single-movie_reviews.php,然后将下面的代码添加到 21 行的下面:
1 2 3 4 | <strong>Genre: </strong> <?php the_terms( $post->ID, 'movie_reviews_movie_genre' , ' ' ); ?> |
<strong>Genre: </strong> <?php the_terms( $post->ID, 'movie_reviews_movie_genre' , ' ' ); ?>
添加后,single-movie_reviews.php 最终的代码应该是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | <?php /*Template Name: New Template */ get_header(); ?> <div id="primary"> <div id="content" role="main"> <?php $mypost = array( 'post_type' => 'movie_reviews', ); $loop = new WP_Query( $mypost ); ?> <!-- Cycle through all posts --> <?php while ( $loop->have_posts() ) : $loop->the_post();?> <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> <header class="entry-header"> <!-- Display featured image in top-aligned floating div --> <div style="float: top; margin: 10px"> <?php the_post_thumbnail( array( 100, 100 ) ); ?> </div> <!-- Display Title and Author Name --> <strong>Title: </strong><?php the_title(); ?><br /> <strong>Director: </strong> <?php echo esc_html( get_post_meta( get_the_ID(), 'movie_director', true ) ); ?> <br /> <strong>Genre: </strong> <?php the_terms( $post->ID, 'movie_reviews_movie_genre' , ' ' ); ?> <br /> <!-- Display yellow stars based on rating --> <strong>Rating: </strong> <?php $nb_stars = intval( get_post_meta( get_the_ID(), 'movie_rating', true ) ); for ( $star_counter = 1; $star_counter <= 5; $star_counter++ ) { if ( $star_counter <= $nb_stars ) { echo '<img src="' . plugins_url( 'Movie-Reviews/images/icon.png' ) . '" />'; } else { echo '<img src="' . plugins_url( 'Movie-Reviews/images/grey.png' ). '" />'; } } ?> </header> <!-- Display movie review contents --> <div class="entry-content"> <?php the_content(); ?> </div> <hr/> </article> <?php endwhile; ?> </div> </div> <?php wp_reset_query(); ?> <?php get_footer(); ?> |
<?php /*Template Name: New Template */ get_header(); ?> <div id="primary"> <div id="content" role="main"> <?php $mypost = array( 'post_type' => 'movie_reviews', ); $loop = new WP_Query( $mypost ); ?> <!-- Cycle through all posts --> <?php while ( $loop->have_posts() ) : $loop->the_post();?> <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> <header class="entry-header"> <!-- Display featured image in top-aligned floating div --> <div style="float: top; margin: 10px"> <?php the_post_thumbnail( array( 100, 100 ) ); ?> </div> <!-- Display Title and Author Name --> <strong>Title: </strong><?php the_title(); ?><br /> <strong>Director: </strong> <?php echo esc_html( get_post_meta( get_the_ID(), 'movie_director', true ) ); ?> <br /> <strong>Genre: </strong> <?php the_terms( $post->ID, 'movie_reviews_movie_genre' , ' ' ); ?> <br /> <!-- Display yellow stars based on rating --> <strong>Rating: </strong> <?php $nb_stars = intval( get_post_meta( get_the_ID(), 'movie_rating', true ) ); for ( $star_counter = 1; $star_counter <= 5; $star_counter++ ) { if ( $star_counter <= $nb_stars ) { echo '<img src="' . plugins_url( 'Movie-Reviews/images/icon.png' ) . '" />'; } else { echo '<img src="' . plugins_url( 'Movie-Reviews/images/grey.png' ). '" />'; } } ?> </header> <!-- Display movie review contents --> <div class="entry-content"> <?php the_content(); ?> </div> <hr/> </article> <?php endwhile; ?> </div> </div> <?php wp_reset_query(); ?> <?php get_footer(); ?>
步骤4:结果
现在我们已经成功添加了一个自定义分类法“Movie Genre”到“movie reviews”这个自定义文章类型了。我们可以在后台添加分类和将分类分配到这自定义文章类型了。
显示附加列(Displaying Additional Columns)
在 WordPress 自定义文章类型的后台 文章列表 页面,已经包含了默认的2个列 - 日期(Date)和评论(Comments),并且我们可以通过它们来排序文章了。如果你想添加更多的列,请按照下面的步骤进行。
步骤1:注册函数
打开 Movie-Reviews.php 文件,在最后一个 ?> 的前面添加下面的代码,用来注册一个函数,它会在你访问文章列表页面时被调用。
1 | add_filter( 'manage_edit-movie_reviews_columns', 'my_columns' ); |
add_filter( 'manage_edit-movie_reviews_columns', 'my_columns' );
在这里,我们通过可变过滤器 manage_edit-(Custom_Post_Type)_columns
,将自定义文章类型的 栏目列表(column list) 作为一个参数传递给函数。
步骤2:完善函数功能
1 2 3 4 5 6 | function my_columns( $columns ) { $columns['movie_reviews_director'] = 'Director'; $columns['movie_reviews_rating'] = 'Rating'; unset( $columns['comments'] ); return $columns; } |
function my_columns( $columns ) { $columns['movie_reviews_director'] = 'Director'; $columns['movie_reviews_rating'] = 'Rating'; unset( $columns['comments'] ); return $columns; }
我们在自定义文章类型的管理面板添加了2个列:Director 和 Rating,并且删除了评论(Comments)这个列。
步骤3:填充列(Populating the Columns)
注册一个函数来填充这些列
1 | add_action( 'manage_posts_custom_column', 'populate_columns' ); |
add_action( 'manage_posts_custom_column', 'populate_columns' );
步骤4:完善函数功能
1 2 3 4 5 6 7 8 9 10 | function populate_columns( $column ) { if ( 'movie_reviews_director' == $column ) { $movie_director = esc_html( get_post_meta( get_the_ID(), 'movie_director', true ) ); echo $movie_director; } elseif ( 'movie_reviews_rating' == $column ) { $movie_rating = get_post_meta( get_the_ID(), 'movie_rating', true ); echo $movie_rating . ' stars'; } } |
function populate_columns( $column ) { if ( 'movie_reviews_director' == $column ) { $movie_director = esc_html( get_post_meta( get_the_ID(), 'movie_director', true ) ); echo $movie_director; } elseif ( 'movie_reviews_rating' == $column ) { $movie_rating = get_post_meta( get_the_ID(), 'movie_rating', true ); echo $movie_rating . ' stars'; } }
在这里,由于任何自定义文章类型的列在呈现时,这写函数都会被执行,所以它会在执行前,检查当前请求的列是否存在。我们已经使用的 get_the_ID() 函数来检索当前行的索引,然后反过来使用 get_post_meta 检索列(column)中的数据。
步骤5:注册为可排序的列(Register Columns as Sortable)
现在让我们来注册一个函数,它会在 WordPress 标识排序的列时被调用。
1 | add_filter( 'manage_edit-movie_reviews_sortable_columns', 'sort_me' ); |
add_filter( 'manage_edit-movie_reviews_sortable_columns', 'sort_me' );
步骤6:完善函数功能
1 2 3 4 5 6 | function sort_me( $columns ) { $columns['movie_reviews_director'] = 'movie_reviews_director'; $columns['movie_reviews_rating'] = 'movie_reviews_rating'; return $columns; } |
function sort_me( $columns ) { $columns['movie_reviews_director'] = 'movie_reviews_director'; $columns['movie_reviews_rating'] = 'movie_reviews_rating'; return $columns; }
此功能可识别两列让他们排序,然后返回该数组。但是,我们的工作还没有完成。
步骤7:按自定义字段排序(Order by Custom Field)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | add_filter( 'request', 'column_ordering' ); add_filter( 'request', 'column_orderby' ); function column_orderby ( $vars ) { if ( !is_admin() ) return $vars; if ( isset( $vars['orderby'] ) && 'movie_reviews_director' == $vars['orderby'] ) { $vars = array_merge( $vars, array( 'meta_key' => 'movie_director', 'orderby' => 'meta_value' ) ); } elseif ( isset( $vars['orderby'] ) && 'movie_reviews_rating' == $vars['orderby'] ) { $vars = array_merge( $vars, array( 'meta_key' => 'movie_rating', 'orderby' => 'meta_value_num' ) ); } return $vars; } |
add_filter( 'request', 'column_ordering' ); add_filter( 'request', 'column_orderby' ); function column_orderby ( $vars ) { if ( !is_admin() ) return $vars; if ( isset( $vars['orderby'] ) && 'movie_reviews_director' == $vars['orderby'] ) { $vars = array_merge( $vars, array( 'meta_key' => 'movie_director', 'orderby' => 'meta_value' ) ); } elseif ( isset( $vars['orderby'] ) && 'movie_reviews_rating' == $vars['orderby'] ) { $vars = array_merge( $vars, array( 'meta_key' => 'movie_rating', 'orderby' => 'meta_value_num' ) ); } return $vars; }
上述函数是根据查询的URL中的变量,关联过滤器和添加一些元素添加到查询数组中。其实WordPress不知道改如何通过“Movie Director”和“Movie Rating”来排序,所以我们需要通过这个函数来告诉它。
我们已经成功地增加了两个可排序的列到管理面板中:
使用自定义分类法创建过滤器(Creating Filters With Custom Taxonomy)
下来,我们将演示如何使用 自定义分类法【custom taxonomies(在例子中,指分类 categories)】添加一个额外的过滤器到 WordPress后台 的自定义文章类型 的列表页面,这样一来,管理员就可以显示 属于某个特定类别 的 自定义文章类型 元素。
步骤1:注册函数
打开 Movie-Reviews.php 文件,在最后一个 ?> 的前面添加下面的代码注册一个函数,这个函数将在点击 WordPress 过滤器下拉列表的时候被调用。
1 | add_action( 'restrict_manage_posts', 'my_filter_list' ); |
add_action( 'restrict_manage_posts', 'my_filter_list' );
步骤2:完善函数功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | function my_filter_list() { $screen = get_current_screen(); global $wp_query; if ( $screen->post_type == 'movie_reviews' ) { wp_dropdown_categories( array( 'show_option_all' => 'Show All Movie Genres', 'taxonomy' => 'movie_reviews_movie_genre', 'name' => 'movie_reviews_movie_genre', 'orderby' => 'name', 'selected' => ( isset( $wp_query->query['movie_reviews_movie_genre'] ) ? $wp_query->query['movie_reviews_movie_genre'] : '' ), 'hierarchical' => false, 'depth' => 3, 'show_count' => false, 'hide_empty' => true, ) ); } } |
function my_filter_list() { $screen = get_current_screen(); global $wp_query; if ( $screen->post_type == 'movie_reviews' ) { wp_dropdown_categories( array( 'show_option_all' => 'Show All Movie Genres', 'taxonomy' => 'movie_reviews_movie_genre', 'name' => 'movie_reviews_movie_genre', 'orderby' => 'name', 'selected' => ( isset( $wp_query->query['movie_reviews_movie_genre'] ) ? $wp_query->query['movie_reviews_movie_genre'] : '' ), 'hierarchical' => false, 'depth' => 3, 'show_count' => false, 'hide_empty' => true, ) ); } }
在这里,我们使用了一个全局变量检测当前显示的文章类型,还使用了一个文章查询变量检查是否已经存在一个现有的过滤器和相应地设置过滤器。函数 wp_dropdown_categories 是用来显示所有使用“Movie Genres”注册的分类法。‘orderby
‘, ‘show_count
‘, ‘hide_empty
‘, ‘depth
‘ etc. 分别表示“按照不同的参数排序”“显示每个分类的文章数”“隐藏不相关的分类”“要显示的最大深度”来分别分类的。
步骤3:显示过滤后的结果
现在的过滤器下拉列表已准备好,我们会写一些代码来显示过滤后的结果。继续添加代码注册一个函数
1 | add_filter( 'parse_query','perform_filtering' ); |
add_filter( 'parse_query','perform_filtering' );
步骤4:完善函数功能
1 2 3 4 5 6 7 | function perform_filtering( $query ) { $qv = &$query->query_vars; if ( ( $qv['movie_reviews_movie_genre'] ) && is_numeric( $qv['movie_reviews_movie_genre'] ) ) { $term = get_term_by( 'id', $qv['movie_reviews_movie_genre'], 'movie_reviews_movie_genre' ); $qv['movie_reviews_movie_genre'] = $term->slug; } } |
function perform_filtering( $query ) { $qv = &$query->query_vars; if ( ( $qv['movie_reviews_movie_genre'] ) && is_numeric( $qv['movie_reviews_movie_genre'] ) ) { $term = get_term_by( 'id', $qv['movie_reviews_movie_genre'], 'movie_reviews_movie_genre' ); $qv['movie_reviews_movie_genre'] = $term->slug; } }
perform_filtering
函数会接收当前的 WordPress 文章查询对象,然后开始按照一个方向查询保存在这些查询对象中的变量。接着,它会验证一个 电影类型(Movie Genre) 是否是这个查询变量中的一部分,如果是,执行查询。
现在,你将可以使用过滤器来显示指定类型的电影:
创建一个存档页(Create an Archive Page)
我们已经为 自定义文章类型 创建了一个自定义模板,我们还可以创建一个自定义的存档页面覆盖默认的存档模板。
步骤1:添加一个回退到存档模板(Adding a Fallback to the Archive Template)
打开 Movie-Reviews.php,找到 include_template_function 这个函数,在11行下面添加如下代码:
1 2 3 4 5 6 | elseif ( is_archive() ) { if ( $theme_file = locate_template( array ( 'archive-movie_reviews.php' ) ) ) { $template_path = $theme_file; } else { $template_path = plugin_dir_path( __FILE__ ) . '/archive-movie_reviews.php'; } |
elseif ( is_archive() ) { if ( $theme_file = locate_template( array ( 'archive-movie_reviews.php' ) ) ) { $template_path = $theme_file; } else { $template_path = plugin_dir_path( __FILE__ ) . '/archive-movie_reviews.php'; }
在使用默认的存档模板前,WordPress会搜索整个当前的主题目录来寻找一个存档模板。这段代码用来检测用户是否在主题目录提供了一个存档模板,如果没有,就检查插件目录。
最后 include_template_function 这个函数的代码应该是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | function include_template_function( $template_path ) { if ( get_post_type() == 'movie_reviews' ) { if ( is_single() ) { // checks if the file exists in the theme first, // otherwise serve the file from the plugin if ( $theme_file = locate_template( array ( 'single-movie_reviews.php' ) ) ) { $template_path = $theme_file; } else { $template_path = plugin_dir_path( __FILE__ ) . '/single-movie_reviews.php'; } } elseif ( is_archive() ) { if ( $theme_file = locate_template( array ( 'archive-movie_reviews.php' ) ) ) { $template_path = $theme_file; } else { $template_path = plugin_dir_path( __FILE__ ) . '/archive-movie_reviews.php'; } } } return $template_path; } |
function include_template_function( $template_path ) { if ( get_post_type() == 'movie_reviews' ) { if ( is_single() ) { // checks if the file exists in the theme first, // otherwise serve the file from the plugin if ( $theme_file = locate_template( array ( 'single-movie_reviews.php' ) ) ) { $template_path = $theme_file; } else { $template_path = plugin_dir_path( __FILE__ ) . '/single-movie_reviews.php'; } } elseif ( is_archive() ) { if ( $theme_file = locate_template( array ( 'archive-movie_reviews.php' ) ) ) { $template_path = $theme_file; } else { $template_path = plugin_dir_path( __FILE__ ) . '/archive-movie_reviews.php'; } } } return $template_path; }
步骤2:创建存档模板
保存刚才的文件,然后新建一个名为 archive-movie_reviews.php 的文件,添加下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <?php get_header(); ?> <section id="primary"> <div id="content" role="main" style="width: 70%"> <?php if ( have_posts() ) : ?> <header class="page-header"> <h1 class="page-title">Movie Reviews</h1> </header> <table> <!-- Display table headers --> <tr> <th style="width: 200px"><strong>Title</strong></th> <th><strong>Director</strong></th> </tr> <!-- Start the Loop --> <?php while ( have_posts() ) : the_post(); ?> <!-- Display review title and author --> <tr> <td><a rel="nofollow noopener noreferrer" href="<?php the_permalink(); ?>"> <?php the_title(); ?></a></td> <td><?php echo esc_html( get_post_meta( get_the_ID(), 'movie_director', true ) ); ?></td> </tr> <?php endwhile; ?> <!-- Display page navigation --> </table> <?php global $wp_query; if ( isset( $wp_query->max_num_pages ) && $wp_query->max_num_pages > 1 ) { ?> <nav id="<?php echo $nav_id; ?>"> <div class="nav-previous"><?php next_posts_link( '<span class="meta-nav">←</span> Older reviews'); ?></div> <div class="nav-next"><?php previous_posts_link( 'Newer reviews <span class= "meta-nav">→</span>' ); ?></div> </nav> <?php }; endif; ?> </div> </section> <br /><br /> <?php get_footer(); ?> |
<?php get_header(); ?> <section id="primary"> <div id="content" role="main" style="width: 70%"> <?php if ( have_posts() ) : ?> <header class="page-header"> <h1 class="page-title">Movie Reviews</h1> </header> <table> <!-- Display table headers --> <tr> <th style="width: 200px"><strong>Title</strong></th> <th><strong>Director</strong></th> </tr> <!-- Start the Loop --> <?php while ( have_posts() ) : the_post(); ?> <!-- Display review title and author --> <tr> <td><a rel="nofollow noopener noreferrer" href="<?php the_permalink(); ?>"> <?php the_title(); ?></a></td> <td><?php echo esc_html( get_post_meta( get_the_ID(), 'movie_director', true ) ); ?></td> </tr> <?php endwhile; ?> <!-- Display page navigation --> </table> <?php global $wp_query; if ( isset( $wp_query->max_num_pages ) && $wp_query->max_num_pages > 1 ) { ?> <nav id="<?php echo $nav_id; ?>"> <div class="nav-previous"><?php next_posts_link( '<span class="meta-nav">←</span> Older reviews'); ?></div> <div class="nav-next"><?php previous_posts_link( 'Newer reviews <span class= "meta-nav">→</span>' ); ?></div> </nav> <?php }; endif; ?> </div> </section> <br /><br /> <?php get_footer(); ?>
在这里,我们使用了一个循环(loop)来获取所有的文章,然后使用一个表格来显示他们。我们还定义了一个导航菜单(a navigation menu),如果这里的一个页面的文章数量超过了后台设置的最大显示数量,就会通过 next_post_links
和 previous_post_links 函数显示导航。
我们使用了全局的 wp_query
对象,其中包含有关当前执行的查询的数据,以便提供页面内容。 函数 get_post_meta
用来获取自定义字段数据。
步骤3:结果
保存该文件,并查看 Movie Reviews 的存档列表页。
好代码教程到这里就要结束了。我希望你已经能够掌握 自定义文章类型 的重点。还有更多的细节等你去发掘!
感谢你的阅读,随时欢迎你的反馈。
原文:http://wp.tutsplus.com/tutorials/plugins/a-guide-to-wordpress-custom-post-types-taxonomies-admin-columns-filters-and-archives/
编译:倡萌@WordPress大学 - wpdaxue.com(稍有改动)
后话:硬着头皮翻译下来,感觉很生涩,又是 2 个小时的煎熬,请原谅我苦逼的英文水平吧。有能力的直接看英文吧。
到此这篇关于WordPress 自定义文章类型 介绍及实例解说(下)就介绍到这了。浪费时间可惜;生而不学可惜;学而无成更可惜。更多相关WordPress 自定义文章类型 介绍及实例解说(下)内容请查看相关栏目,小编编辑不易,再次感谢大家的支持!