Ghét phải là người mang tin xấu nhưng WordPress đã mã hóa chức năng Mẫu trang thành loại bài đăng "trang" , ít nhất là trong phiên bản 3.0 (có thể thay đổi trong các phiên bản trong tương lai nhưng không có sáng kiến cụ thể nào tôi biết để thay đổi nó Tuy nhiên, đây là một trong số rất ít lần tôi đấu tranh để tìm ra cách khắc phục thứ gì đó mà không hack lõi.)
Giải pháp tôi đã đưa ra là về cơ bản sao chép mã có liên quan từ lõi WordPress và sửa đổi nó theo nhu cầu của chúng tôi. Dưới đây là các bước (số dòng từ v3.0.1):
Sao chép page_attributes_meta_box()
chức năng từ dòng 535 /wp-admin/includes/meta-boxes.php
và sửa đổi cho phù hợp.
Mã hóa một add_meta_boxes
cái móc để thêm metabox được tạo trong # 1.
Sao chép get_page_templates()
chức năng từ dòng 166 /wp-admin/includes/theme.php
và sửa đổi cho phù hợp.
Sao chép page_template_dropdown()
chức năng từ dòng 2550 /wp-admin/includes/template.php
và sửa đổi cho phù hợp.
Thêm một mẫu bài viết vào chủ đề của bạn.
Mã một save_post
hook để cho phép lưu trữ tên tệp bài đăng khi lưu.
Mã một single_template
hook để cho phép tải mẫu bài đăng cho các bài đăng liên quan.
Bây giờ với nó!
1. Sao chép page_attributes_meta_box()
chức năng
Là bước đầu tiên của chúng tôi, bạn cần sao chép page_attributes_meta_box()
chức năng từ dòng 535 /wp-admin/includes/meta-boxes.php
và tôi đã chọn đổi tên nó post_template_meta_box()
. Vì bạn chỉ yêu cầu các mẫu trang, tôi đã bỏ qua mã để chỉ định một bài đăng gốc và để chỉ định thứ tự làm cho mã đơn giản hơn nhiều. Tôi cũng đã chọn sử dụng postmeta cho việc này thay vì cố gắng sử dụng lại thuộc tính page_template
đối tượng để tránh và sự không tương thích tiềm ẩn gây ra bởi khớp nối không chủ ý. Vì vậy, đây là mã:
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. Mã một add_meta_boxes
cái móc
Bước tiếp theo là thêm metabox bằng add_meta_boxes
hook:
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. Sao chép get_page_templates()
chức năng
Tôi giả định rằng sẽ chỉ có ý nghĩa để phân biệt giữa các mẫu trang và mẫu bài do đó cần một get_post_templates()
chức năng dựa trên get_page_templates()
dòng 166 của /wp-admin/includes/theme.php
. Nhưng thay vì sử dụng Template Name:
điểm đánh dấu, mẫu trang nào sử dụng chức năng này sử dụng Post Template:
điểm đánh dấu thay vì bạn có thể thấy bên dưới.
Tôi cũng đã lọc ra kiểm tra functions.php
(không chắc bao get_page_templates()
giờ hoạt động chính xác mà không có điều đó, nhưng bất cứ điều gì!) Và điều duy nhất còn lại là thay đổi các tham chiếu đến từ page
để post
bảo trì dễ đọc trên đường:
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. Sao chép page_template_dropdown()
chức năng
Tương tự sao chép page_template_dropdown()
từ dòng 2550 của /wp-admin/includes/template.php
để tạo post_template_dropdown()
và chỉ cần thay đổi nó để gọi get_post_templates()
thay thế:
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 "\n\t<option value='".$templates[$template]."' $selected>$template</option>";
endforeach;
}
5. Thêm một mẫu bài
Bước tiếp theo là thêm một mẫu bài đăng để thử nghiệm. Sử dụng Post Template:
điểm đánh dấu được đề cập trong bước 3 sao chép single.php
từ chủ đề của bạn vào single-test.php
và thêm tiêu đề nhận xét sau ( hãy chắc chắn sửa đổi một cái gì đó single-test.php
để bạn có thể biết nó đang tải thay vì single.php
) :
/**
* Post Template: My Test Template
*/
Khi bạn đã thực hiện các bước # 1 đến # 5, bạn có thể thấy metabox "Bài mẫu" xuất hiện trên trang biên tập bài đăng của mình:
(nguồn: mikechinkel.com )
6. Mã một save_post
cái móc
Bây giờ bạn đã có trình soạn thảo bình phương, bạn cần phải thực sự lưu tên tệp mẫu trang của mình vào postmeta khi người dùng nhấp vào "Xuất bản". Đây là mã cho điều đó:
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. Mã một single_template
cái móc
Và cuối cùng, bạn cần phải thực sự có được WordPress để sử dụng các mẫu bài đăng mới của bạn. Bạn làm điều đó bằng cách móc single_template
và trả lại tên mẫu mong muốn của bạn cho những bài đăng đã được gán:
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;
}
Và đó là về nó!
LƯU Ý rằng tôi đã không xem xét các loại bài tùy chỉnh , chỉ post_type=='post'
. Theo ý kiến của tôi, việc giải quyết các loại bài đăng tùy chỉnh sẽ yêu cầu phân biệt giữa các loại bài đăng khác nhau và trong khi không quá khó khăn, tôi đã không thử điều đó ở đây.