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: