问题描述
(主持人注意:标题最初是 「如何将”Page Attributes” 和/或」 页面属性> 模板 「选择器添加到 POSTS 编辑器」)
WP 目前只允许将”template” 分配给 Pages(即 post_type=='page'
) 。我也想将此功能扩展到帖子 (即 post_type=='post'
) 。
如何添加”Page Attributes” 元框,更具体地说,模板切换到帖子编辑器?
我假设这是代码,我将放在我的 functions.php
为我的主题。
更新:我已经设法添加硬编码模板下拉菜单到我的帖子编辑器,只需将选择框 html 添加到我现有的自定义元选项框。这是我正在使用的代码…
add_meta_box('categorydiv2', __('Post Options'), 'post_categories_meta_box_modified', 'post', 'side', 'high');
这里是写出选项和模板选择框的功能…
//adds the custom categories box
function post_categories_meta_box_modified() {
global $post;
if( get_post_meta($post->ID, '_noindex', true) ) $noindexChecked = " checked='checked'";
if( get_post_meta($post->ID, '_nofollow', true) ) $nofollowChecked = " checked='checked'";
?>
<div id="categories-all" class="ui-tabs-panel">
<ul id="categorychecklist" class="list:category categorychecklist form-no-clear">
<li id='noIndex' class="popular-category"><label class="selectit"><input value="noIndex" type="checkbox" name="chk_noIndex" id="chk_noIndex"<?php echo $noindexChecked ?> /> noindex</label></li>
<li id='noFollow' class="popular-category"><label class="selectit"><input value="noFollow" type="checkbox" name="chk_noFollow" id="chk_noFollow"<?php echo $nofollowChecked ?> /> nofollow</label></li>
</ul>
<p><strong>Template</strong></p>
<label class="screen-reader-text" for="page_template">Post Template</label><select name="page_template" id="page_template">
<option value='default'>Default Template</option>
<option value='template-wide.php' >No Sidebar</option>
<option value='template-salespage.php' >Salespage</option>
</select>
</div>
<?php
}
最后,代码捕获所选值保存…
function save_post_categories_meta($post_id) {
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return $post_id;
$noIndex = $_POST['chk_noIndex'];
$noFollow = $_POST['chk_noFollow'];
update_post_meta( $post_id, '_noindex', $noIndex );
update_post_meta( $post_id, '_nofollow', $noFollow );
return $post_id;
}
现在,我相信剩下的是 (1) 捕获所选模板并将其添加到此帖子的后期元素中,(2) 修改 index.php 和 single.php,以便它使用所选的模板。
最佳解决方案
不喜欢成为坏消息的承载者,但是 WordPress 将页面模板功能重新编码为”page” 的帖子类型,至少在 v3.0 中 (可能会在将来的版本中更改,但是我没有注意到改变它的具体方案。所以这是很少的时候,我正在努力找出如何摆脱一些没有黑客核心的东西。)
我提出的解决方案是从 WordPress 核心基本上复制相关代码,并将其修改为我们的需求。以下是步骤 (行号为 v3.0.1):
-
复制
/wp-admin/includes/meta-boxes.php
的第 535 行page_attributes_meta_box()
功能,并进行修改。 -
编写一个
add_meta_boxes
钩子来添加在#1 中创建的 metabox 。 -
复制
/wp-admin/includes/theme.php
的第 166 行get_page_templates()
功能,修改即可。 -
从
/wp-admin/includes/template.php
的 2550 行复制page_template_dropdown()
功能,并进行修改。 -
添加一个帖子模板到您的主题。
-
编写一个
save_post
钩子,以保存保存后的模板文件名。 -
编写一个
single_template
钩子,以启用相关帖子的帖子模板的加载。
现在吧!
1. 复制 page_attributes_meta_box()
功能
作为我们的第一步,您需要从/wp-admin/includes/meta-boxes.php
的第 535 行复制 page_attributes_meta_box()
功能,我选择将其重命名为 post_template_meta_box()
。由于您只要求页面模板,因此我省略了指定父帖子的代码,并指定使代码更简单的顺序。我也选择使用 postmeta,而不是尝试重用 page_template
对象属性,以避免由于无意耦合引起的潜在的不兼容性。所以这里是代码:
function post_template_meta_box($post) {
if ( 'post' == $post->post_type && 0 != count( get_post_templates() ) ) {
$template = get_post_meta($post->ID,'_post_template',true);
?>
<label class="screen-reader-text" for="post_template"><?php _e('Post Template') ?></label><select name="post_template" id="post_template">
<option value='default'><?php _e('Default Template'); ?></option>
<?php post_template_dropdown($template); ?>
</select>
<?php
} ?>
<?php
}
2. 编写一个 add_meta_boxes
钩子
下一步是使用 add_meta_boxes
钩子添加 metabox:
add_action('add_meta_boxes','add_post_template_metabox');
function add_post_template_metabox() {
add_meta_box('postparentdiv', __('Post Template'), 'post_template_meta_box', 'post', 'side', 'core');
}
3. 复制 get_page_templates()
功能
我认为区分页面模板和帖子模板是有意义的,因此需要基于/wp-admin/includes/theme.php
第 166 行的 get_page_templates()
的 get_post_templates()
功能。但是,不使用 Template Name:
标记,该页面模板使用该功能使用 Post Template:
标记,而您可以在下面看到。
我也滤除了 functions.php
的检查 (不知道 get_page_templates()
如何正常工作没有,但无论如何!) 而唯一的事情是将 page
这个词改为 post
,以便维护可读性:
function get_post_templates() {
$themes = get_themes();
$theme = get_current_theme();
$templates = $themes[$theme]['Template Files'];
$post_templates = array();
if ( is_array( $templates ) ) {
$base = array( trailingslashit(get_template_directory()), trailingslashit(get_stylesheet_directory()) );
foreach ( $templates as $template ) {
$basename = str_replace($base, '', $template);
if ($basename != 'functions.php') {
// don't allow template files in subdirectories
if ( false !== strpos($basename, '/') )
continue;
$template_data = implode( '', file( $template ));
$name = '';
if ( preg_match( '|Post Template:(.*)$|mi', $template_data, $name ) )
$name = _cleanup_header_comment($name[1]);
if ( !empty( $name ) ) {
$post_templates[trim( $name )] = $basename;
}
}
}
}
return $post_templates;
}
4. 复制 page_template_dropdown()
功能
同样从/wp-admin/includes/template.php
的第 2550 行复制 page_template_dropdown()
,创建 post_template_dropdown()
,然后将其更改为调用 get_post_templates()
:
function post_template_dropdown( $default = '' ) {
$templates = get_post_templates();
ksort( $templates );
foreach (array_keys( $templates ) as $template )
: if ( $default == $templates[$template] )
$selected = " selected='selected'";
else
$selected = '';
echo "nt<option value='".$templates[$template]."' $selected>$template</option>";
endforeach;
}
5. 添加一个帖子模板
下一步是添加一个 post 模板进行测试。使用步骤 3 中提到的 Post Template:
标记将 single.php
从您的主题复制到 single-test.php
,并添加以下注释标题 (请确保在 single-test.php
中修改某些内容,以便您可以知道它正在加载而不是 single.php
):
/**
* Post Template: My Test Template
*/
一旦您完成步骤#1 到#5,您可以看到您的”Post Templates” metabox 出现在您的帖子编辑器页面上:
6. 编写一个 save_post
钩子
现在你的编辑器已经平仓了,当用户点击”Publish” 时,您需要实际将页面模板文件名保存到 postmeta 。这是代码:
add_action('save_post','save_post_template',10,2);
function save_post_template($post_id,$post) {
if ($post->post_type=='post' && !empty($_POST['post_template']))
update_post_meta($post->ID,'_post_template',$_POST['post_template']);
}
7. 编写一个 single_template
钩子
最后你需要真正让 WordPress 使用你的新帖子模板。您可以通过挂接 single_template
并为已分配的帖子返回所需的模板名称:
add_filter('single_template','get_post_template_for_template_loader');
function get_post_template_for_template_loader($template) {
global $wp_query;
$post = $wp_query->get_queried_object();
if ($post) {
$post_template = get_post_meta($post->ID,'_post_template',true);
if (!empty($post_template) && $post_template!='default')
$template = get_stylesheet_directory() . "/{$post_template}";
}
return $template;
}
这就是它!
注意我没有考虑到自定义帖子类型,只有 post_type=='post'
。在我看来,解决定制职位类型需要区分不同的职位类型,而不是过分困难,我没有在这里尝试。
参考文献
注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。