I have a custom post with a lot of meta boxes. I recently tried to add some dynamic metaboxes, using this question: Create more Meta Boxes as needed
I managed to get the metaboxes to add nicely, the jquery works, everything works except the save_post action – the “Reviews” save nicely, but the “Screenings” don’t. What have I done wrong in my code? I’m sure it must be something very simple that I’m overlooking, perhaps with the nonces?
Edit: I know I can do all of this with one save_post
, and that works if I only have 1 of these dynamic metaboxes, but if I add a second (or more) dynamic metabox section, that data doesn’t save.
Edit: If necessary, I can post my entire custom-posts.php function file to pastebin or something, but I have just included what I think is the relevant snippet here for brevity
Edit: Updated code…
<?php
add_action('save_post', 'save_postdata'); // saves post data from another function earlier on
add_action('save_post', 'save_postdata_dynamic_reviews_metabox' );
add_meta_box("film-reviews", "Reviews", "print_dynamic_reviews_metabox", "film", "normal", "low");
add_action('save_post', 'save_postdata_dynamic_screenings_metabox' );
add_meta_box("film-screenings", "Screenings", "print_dynamic_screenings_metabox", "film", "normal", "low");
/* Prints the box content */
function print_dynamic_reviews_metabox() {
global $post;
// Use nonce for verification
echo '<input type="hidden" name="reviews_noncename" id="reviews_noncename" value="' . wp_create_nonce( 'reviews-nonce' ) . '" />';
echo '<div id="meta_inner-reviews">';
echo '<ol id="reviews-meta">';
$reviews = get_post_meta($post->ID,'reviews',true); //get any previously saved meta as an array so we can display it
// print_r($reviews);
$c = 0;
if( is_array($reviews) ) {
foreach($reviews as $review ) {
if (isset($review['review-name']) || isset($review['review-link']) ) {
echo '
<li><span class="remove-review" title="Delete">Remove</span>
<label><strong>Review Name/Title:</strong> <input type="text" class="meta-review-name saveddata" name="reviews['.$c.'][review-name]" value="'.$review['review-name'].'" /></label>
<label><strong>Review URL:</strong> (don\'t forget the http://) <input type="text" class="meta-review-url saveddata" name="reviews['.$c.'][review-url]" value="'.$review['review-url'].'" /></label>';
echo '<span class="remove-review" title="Delete">Remove</span></li>';
$c = $c +1;
} // ends if isset $award[album]
} // ends foreach
} // ends if (is_array)
echo '</ol>';
echo '<span class="add-review">Add New Review</span>';
?>
<script>
var $ =jQuery.noConflict();
$(document).ready(function() {
var count = <?php echo $c; ?>;
$(".add-review").click(function() {
count = count + 1;
$('#reviews-meta').append('<li><span class="remove-review" title="Delete">Remove</span> <label><strong>Review Name/Title:</strong> <input type="text" class="meta-review-name" name="reviews['+count+'][review-name]" value="" /></label> <label><strong>Review URL:</strong> (don\'t forget the http://) <input type="text" class="meta-review-url" name="reviews['+count+'][review-url]" value="" /></label></li> <span class="remove-review" title="Delete">Remove</span>');
return false;
});
$(".remove-review").live('click', function() {
$(this).parent().remove();
});
});
</script>
<?php
echo '</div>'; // ends div#meta_inner
} // ends function print_dynamic_reviews_metabox()
function save_postdata_dynamic_reviews_metabox( $post_id ) {
// verify if this is an auto save routine.
// If it is our form has not been submitted, so we dont want to do anything
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
return;
}
// Check permissions
if ( 'page' == $_POST['post_type'] ) { if ( !current_user_can( 'edit_page', $post_id )) { return $post_id; }}
elseif ( !current_user_can( 'edit_post', $post_id )) { return $post_id;}
// verify this came from the our screen and with proper authorization,
// because save_post can be triggered at other times
if (isset($_POST['reviews_noncename'])){
if ( !wp_verify_nonce( $_POST['reviews_noncename'], 'reviews-nonce' ) )
return;
}else{return;}
// OK, we're authenticated: we need to find and save the data
$reviews = $_POST['reviews'];
update_post_meta($post_id,'reviews',$reviews);
} // ends function save_postdata_dynamic_reviews_metabox
/* Prints the box content */
function print_dynamic_screenings_metabox() {
global $post;
// Use nonce for verification
echo '<input type="hidden" name="screenings_noncename" id="screenings_noncename" value="' . wp_create_nonce( 'screenings-nonce' ) . '" />';
echo '<div id="meta_inner-screenings">';
echo '<ol id="screenings-meta">';
$screenings= get_post_meta($post->ID,'screenings',true); //get any previously saved meta as an array so we can display it
// print_r($screenings);
$c = 0;
if( is_array($screenings) ) {
foreach($screenings as $screening ) {
if (isset($screening['screening-festival-name']) || isset($screening['screening-festival-date']) ) {
echo '
<li><span class="remove-screening" title="Delete">Remove</span>
<label><strong>Festival Name:</strong> <input type="text" class="meta-screening-festival-name saveddata" name="screenings['.$c.'][screening-festival-name]" value="'.$screening['screening-festival-name'].'" /></label>
<label><strong>Festival Date:</strong> <input type="text" class="meta-screening-festival-date saveddata" name="screenings['.$c.'][screening-festival-date]" value="'.$screening['screening-festival-date'].'" /></label>';
echo '<span class="remove-screening" title="Delete">Remove</span></li>';
$c = $c +1;
} // ends if isset $award[album]
} // ends foreach
} // ends if (is_array)
echo '</ol>';
echo '<span class="add-screening">Add New Screening</span>';
?>
<script>
var $ =jQuery.noConflict();
$(document).ready(function() {
var count = <?php echo $c; ?>;
$(".add-screening").click(function() {
count = count + 1;
$('#screenings-meta').append('<li><span class="remove-screening" title="Delete">Remove</span> <label><strong>Festival Name:</strong> <input type="text" class="meta-screening-festival-name" name="screenings['+count+'][screening-festival-name]" value="" /></label> <label><strong>Festival Date:</strong> <input type="text" class="meta-screening-festival-date" name="screenings['+count+'][screening-festival-date]" value="" /></label> <span class="remove-screening" title="Delete">Remove</span>');
return false;
});
$(".remove-screening").live('click', function() {
$(this).parent().remove();
});
});
</script>
<?php
echo '</div>'; // ends div#meta_inner
} // ends function print_dynamic_screenings_metabox()
function save_postdata_dynamic_screenings_metabox( $post_id ) {
// verify if this is an auto save routine.
// If it is our form has not been submitted, so we dont want to do anything
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
return;
}
// Check permissions
if ( 'page' == $_POST['post_type'] ) { if ( !current_user_can( 'edit_page', $post_id )) { return $post_id; }}
elseif ( !current_user_can( 'edit_post', $post_id )) { return $post_id;}
// verify this came from the our screen and with proper authorization,
// because save_post can be triggered at other times
if (isset($_POST['screenings_noncename'])){
if ( !wp_verify_nonce( $_POST['screenings_noncename'], 'screenings-nonce' ) )
return;
}else{return;}
// OK, we're authenticated: we need to find and save the data
$screenings= $_POST['screenings'];
update_post_meta($post_id,'screenings',$screenings);
} // ends function save_postdata_dynamic_screenings_metabox
?>