(Moderators note: Title was originally “How can I add the “Page Attributes” and/or “Page Attributes > Template” selector to POSTS editor”)
WP currently only allows the assignment of a “template” to Pages (i.e. post_type=='page'
.) I’d like to extend this functionality to Posts as well (i.e. post_type=='post'
.)
How can I add the “Page Attributes” meta box and more specifically, the template switcher to the posts editor?
I’m assuming this is code I will place in my functions.php
for my theme.
UPDATE: I’ve managed to add the hardcoded templates pulldown menu to my post editor, by simply adding the select box html to my existing custom meta options box. Here’s the code I’m using for that…
add_meta_box('categorydiv2', __('Post Options'), 'post_categories_meta_box_modified', 'post', 'side', 'high');
And here’s the function that writes out the options and the template select box…
//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
}
And finally, the code to capture the selected values on save…
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;
}
Now, I believe all that’s left is (1) capturing the selected template and adding it to the post meta for this post and (2) modifying index.php and single.php so that it uses the chosen template.
Hate to be the bearer of bad news but WordPress hardcodes the Page Template functionality to the “page” post type, at least in v3.0 (that might change in future versions but there’s not a specific initiative I’m aware of to change it yet. So this is one of the very few times I’m struggling to figure out how to get around something without hacking core.)
The solution I’ve come up with is to basically copy the relevant code from WordPress core and modify it to our needs. Here are the steps (the line numbers are from v3.0.1):
Copy the
page_attributes_meta_box()
function from line 535 of/wp-admin/includes/meta-boxes.php
and modify to suit.Code an
add_meta_boxes
hook to add the metabox created in #1.Copy the
get_page_templates()
function from line 166 of/wp-admin/includes/theme.php
and modify to suit.
Copy the
page_template_dropdown()
function from line 2550 of/wp-admin/includes/template.php
and modify to suit.Add a Post Template to your theme.
Code a
save_post
hook to enable storing of the post template file name upon save.Code a
single_template
hook to enable loading of the post template for the associated posts.Now on with it!
1. Copy the
page_attributes_meta_box()
functionAs our first step you need to copy the
page_attributes_meta_box()
function from line 535 of/wp-admin/includes/meta-boxes.php
and I’ve chosen to rename itpost_template_meta_box()
. Since you only asked for page templates I omitted the code for specifying a parent post and for specifying the order which makes the code much simpler. I also chose to use postmeta for this rather than try to reuse thepage_template
object property in order to avoid and potential incompatibilities caused by unintentional coupling. So here’s the code:2. Code an
add_meta_boxes
hookNext step is to add the metabox using the
add_meta_boxes
hook:3. Copy the
get_page_templates()
functionI assumed it would only make sense to differentiate between page templates and post template thus the need for a
get_post_templates()
function based onget_page_templates()
from line 166 of/wp-admin/includes/theme.php
. But instead of using theTemplate Name:
marker which page templates use this function uses aPost Template:
marker instead which you can see below.I also filtered out inspection of
functions.php
(not sure howget_page_templates()
ever worked correctly without that, but whatever!) And the only thing left is to change references to the wordpage
topost
for maintenance readability down the road:4. Copy the
page_template_dropdown()
functionSimilarly copy
page_template_dropdown()
from line 2550 of/wp-admin/includes/template.php
to createpost_template_dropdown()
and simply change it to callget_post_templates()
instead:5. Add a Post Template
Next step is to add a post template for testing. Using the
Post Template:
marker mentioned in step #3 copysingle.php
from your theme tosingle-test.php
and add the following comment header (be sure to modify something insingle-test.php
so you can tell it is loading instead ofsingle.php
):Once you’ve done steps #1 thru #5 you can see your “Post Templates” metabox appear on your post editor page:
(source: mikeschinkel.com)
6. Code a
save_post
hookNow that you have the editor squared away you need to actually save your page template file name to postmeta when the user clicks “Publish”. Here’s the code for that:
7. Code a
single_template
hookAnd lastly you need to actually get WordPress to use your new post templates. You do that by hooking
single_template
and returning your desired template name for those posts that have had one assigned:And that’s about it!
NOTE that I did not take into consideration Custom Post Types, only
post_type=='post'
. In my opinion addressing custom post types would require differentiating between the different post types and, while not overly difficult, I didn’t attempt that here.WordPress allows you to add Meta to Categories using a plugin:
To do this you need to add one of the various extensions that adds meta to categories (mimicking what pages get out of the box), Simple Term Meta does the job nicely.
N.B. WordPress 3.x is needed for extending Categories.
After that you can use:
Use Functions.php to add methods to do what you want e.g.
Calling new fields in themes is easy:
More details and examples:
http://www.wphub.com/adding-metadata-taxonomy-terms/