The post metadata can store multiple values either as distinct entries in the postmeta
table, or as one entry with the value as a serialized PHP array. The serialization may require less code, but the distinct entries allow faster querying later (“give me all posts that have at least option A of the multicheck checked”).
I took the code you linked to and made the following changes to allow a “multicheck”:
// in show():
// Line 254: replace it by:
$meta = get_post_meta($post->ID, $field['id'], 'multicheck' != $field['type'] /* If multicheck this can be multiple values */);
// Add the following to the switch:
case 'multicheck':
foreach ( $field['options'] as $value => $name ) {
// Append `[]` to the name to get multiple values
// Use in_array() to check whether the current option should be checked
echo '<input type="checkbox" name="', $field['id'], '[]" id="', $field['id'], '" value="', $value, '"', in_array( $value, $meta ) ? ' checked="checked"' : '', ' /> ', $name, '<br/>';
}
break;
// In save():
// Line 358: replace it by:
$old = get_post_meta($post_id, $name, 'multicheck' != $field['type'] /* If multicheck this can be multiple values */);
// Lines 409-413: Wrap them in an else-clause, and prepend them by:
if ( 'multicheck' == $field['type'] ) {
// Do the saving in two steps: first get everything we don't have yet
// Then get everything we should not have anymore
if ( empty( $new ) ) {
$new = array();
}
$aNewToAdd = array_diff( $new, $old );
$aOldToDelete = array_diff( $old, $new );
foreach ( $aNewToAdd as $newToAdd ) {
add_post_meta( $post_id, $name, $newToAdd, false );
}
foreach ( $aOldToDelete as $oldToDelete ) {
delete_post_meta( $post_id, $name, $oldToDelete );
}
} else {
// The original lines 409-413
}
Two extra changes to prevent PHP warnings when WP_DEBUG
is enabled:
// Line 337:
if ( ! isset( $_POST['wp_meta_box_nonce'] ) || !wp_verify_nonce($_POST['wp_meta_box_nonce'], basename(__FILE__))) {
// Line 359:
$new = isset( $_POST[$field['id']] ) ? $_POST[$field['id']] : null;
With these changes, you can use a “multicheck” by defining it like this:
array(
'name' => 'Multicheck',
'id' => $prefix . 'multicheck',
'type' => 'multicheck',
'options' => array(
'a' => 'Apple',
'b' => 'Banana',
'c' => 'Cherry',
),
)