I have the following code which adds a custom post type to the admin dash and a custom meta box to the post edit window:
function teasers_custom_init() {
$labels = array(
'name' => 'Teasers',
'singular_name' => 'Teaser',
'add_new' => 'Add New',
'add_new_item' => 'Add New Teasers',
'edit_item' => 'Edit Teaser',
'new_item' => 'New Teaser',
'all_items' => 'All Teasers',
'view_item' => 'View Teaser',
'search_items' => 'Search Teasers',
'not_found' => 'No teasers found',
'not_found_in_trash' => 'No teasers found in Trash',
'parent_item_colon' => 'Parent Page',
'menu_name' => 'Teasers'
);
$args = array(
'labels' => $labels,
'description' => 'set slider panels with loop times',
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'Teasers' ),
'capability_type' => 'page',
'has_archive' => true,
'hierarchical' => true,
'menu_position' => 60,
'supports' => array( 'title', 'thumbnail', 'page-attributes'),
);
register_post_type( 'teasers', $args );
}
add_action( 'init', 'teasers_custom_init' );
//adding the meta box when the admin panel initialises
add_action("admin_init", "admin_init");
// this adds the save teaser function on save post
add_action('save_post', 'save_teaser');
function admin_init(){
add_meta_box('teaser_loop', 'Loop Time', 'loop_meta', 'teasers', 'normal', 'default');
}
// callback function of add meta box that displays the meta box in the post edit screen
function loop_meta($post, $args){
$teaser_loop = get_post_meta($post->ID, 'teaser_loop', true);
?>
<label>Teaser Loop: </label><input type="text" name="teaser_loop" value="<?php echo $teaser_loop; ?>" /><br/>
<?php
}
// saving the teaser
function save_teaser(){
global $post;
update_post_meta($post->ID, 'teaser_loop', $_POST['teaser_loop']);
}
My question is if I want to add an additional meta box, what is the best approach?
I tried adding another add_meta_box call in admin_init function and also created an additional callback function for this meta box html but nothing was generated on the front end. Any pointers would be great.
EDIT: So this is how I did it for more than one meta box (this works):
//adding the meta box when the admin panel initialises
add_action("admin_init", "admin_init");
// this adds the save teaser function on save post
add_action('save_post', 'save_teaser');
function admin_init(){
add_meta_box('teaser_loop', 'Loop Time', 'loop_meta_1', 'teasers', 'normal', 'default');
add_meta_box('teaser_link', 'Teaser Link', 'loop_meta_2', 'teasers', 'normal', 'default');
}
// back function of add meta box that displays the meta box in the post edit screen
function loop_meta_1($post, $args){
$teaser_loop = get_post_meta($post->ID, 'teaser_loop', true);
?>
<label>Teaser Loop: </label><input type="text" name="teaser_loop" value="<?php echo $teaser_loop; ?>" /><br/>
<?php
}
function loop_meta_2($post, $args){
$teaser_link = get_post_meta($post->ID, 'teaser_link', true);
?>
<label>Teaser Link: </label><input type="text" name="teaser_link" value="<?php echo $teaser_link; ?>" /><br/>
<?php
}
// saving the teaser
function save_teaser(){
global $post;
update_post_meta($post->ID, 'teaser_loop', $_POST['teaser_loop']);
update_post_meta($post->ID, 'teaser_link', $_POST['teaser_link']);
}
It can be completely encapsulated in a class. Here, I'm not dealing with adding the Custom Post Type, and there are only two simple output fields, text and checkbox. A full fledged working code should take care of each of the desired input types.
<?php
/**
* Plugin Name: Sample Dynamic Meta Boxes
* Plugin URI: http://stackoverflow.com/q/13903529/1287812
* Author: brasofilo
*/
class B5F_Dynamic_Meta_Boxes
{
private $boxes;
# Safe to start up
public function __construct( $args )
{
$this->boxes = $args;
add_action( 'plugins_loaded', array( $this, 'start_up' ) );
}
public function start_up()
{
add_action( 'add_meta_boxes', array( $this, 'add_mb' ) );
}
public function add_mb()
{
foreach( $this->boxes as $box )
add_meta_box(
$box['id'],
$box['title'],
array( $this, 'mb_callback' ),
$box['post_type'],
isset( $box['context'] ) ? $box['context'] : 'normal',
isset( $box['priority'] ) ? $box['priority'] : 'default',
$box['args']
);
}
# Callback function, uses helper function to print each meta box
public function mb_callback( $post, $box )
{
switch( $box['args']['field'] )
{
case 'textfield':
$this->textfield( $box, $post->ID );
break;
case 'checkbox':
$this->checkbox( $box, $post->ID );
break;
}
}
private function textfield( $box, $post_id )
{
$post_meta = get_post_meta( $post_id, $box['id'], true );
printf(
'<label>%s: <input type="text" name="%s" value="%s" /></label> <small>%s</small><br/>',
$box['title'],
$box['id'],
$post_meta,
$box['args']['desc']
);
}
private function checkbox( $box, $post_id )
{
$post_meta = get_post_meta( $post_id, $box['id'], true );
printf(
'<label>%s: </label><input type="checkbox" name="%s" %s /> <small>%s</small><br/>',
$box['title'],
$box['id'],
checked( 1, $post_meta, false ),
$box['args']['desc']
);
}
}
# ADD TWO META BOXES - DIFFERENT POST TYPES - DIFFERENT CONTEXTS AND PRIORITIES
$args = array(
array(
'id' => 'teaser_loop',
'title' => 'Loop Time',
'post_type' => 'post',
'args' => array(
'desc' => 'Enter the time',
'field' => 'textfield',
)
),
array(
'id' => 'teaser_link',
'title' => 'Loop Link',
'post_type' => 'page',
'context' => 'side',
'priority' => 'high',
'args' => array(
'desc' => 'Open link',
'field' => 'checkbox',
)
),
);
new B5F_Dynamic_Meta_Boxes( $args );
# ADD ANOTHER META BOX TO ANOTHER POST TYPE
$more_args = array(
array(
'id' => 'extra_box',
'title' => 'And another one',
'post_type' => 'teaser',
'args' => array(
'desc' => 'Open link',
'field' => 'textfield',
)
),
);
new B5F_Dynamic_Meta_Boxes( $more_args );
This is just a skeleton, from here there's a lot to be written. Some examples:
Custom Metaboxes and Fields for WordPress
HM Custom Meta Boxes for WordPress
My Wordpress Meta box Class
Meta Box plugin
You can add metabox to custom post type with following code.
First, create metabox
add_action('admin_init', 'my_theme_on_admin_init');
function my_theme_on_admin_init() {
add_meta_box('my_metabox',
__('My metabox', 'textdomain'),
'my_metabox_render',
'my_custom_post_type', 'normal', 'high'
);
}
Notice, that my_custom_post_type
is a name of you custom post type and my_metabox_render
- name of a function that renders metabox.
Rendering function should create all nessesary fields
function my_metabox_render($post) {
$data = get_post_meta($post->ID, '_meta_key', true);
// Use nonce for verification
wp_nonce_field('add_my_meta', 'my_meta_nonce');
?>
<div class="inside">
<table class="form-table">
<tr valign="top">
<th scope="row"><label for="my_meta_value"><?php _e('My meta', 'textdomain'); ?></label></th>
<td><textarea id="my_meta_value" name="my_meta_value" cols="40" rows="5"><?php echo (isset($data)) ? $data : ''; ?></textarea></td>
</tr>
</table>
</div>
<?php
}
Than you should update you metadata when user saves post
add_action('wp_insert_post', 'save_my_meta', 10, 2);
function save_my_meta($id) {
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )
return $id;
if (!current_user_can('edit_posts'))
return;
if (!isset($id))
$id = (int) $_REQUEST['post_ID'];
if (isset($_POST['my_meta_value']) && wp_verify_nonce($_POST['my_meta_value'], 'add_my_meta')) {
$data = $_POST['my_meta_value'];
if (isset($data)) {
update_post_meta($id, '_meta_key', $data);
}
else {
delete_post_meta($id, '_meta_key');
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With