1

I tried to create a custom meta box with checkboxes, generated from a loop of a custom-post-type. I found this example here on WP Development, but I can not figure out why the boxes won't save.

My code looks like this:

function anwaelte_display_meta_box( $post ) { 
    global $loop_anwaelte;
    $loop_anwaelte = array();   
    wp_nonce_field( plugin_basename( __FILE__ ), 'anwaelte-nonce-field' );

    $args = array(
        'post_type' => 'anwaelte',
        'orderby'   => 'title',
        'order'     => 'ASC'
     );
    $query_anwaelte = new WP_Query( $args );

    while ( $query_anwaelte->have_posts() ) : $query_anwaelte->the_post(); 
        $id_anwalt = get_the_ID();
        $anwalt = get_post( $id_brand, ARRAY_A );
        $slug_anwalt = $anwalt['post_name'];
        $titolo_anwalt = $anwalt['post_title'];
        $loop_anwaelte[] = $slug_anwalt;
        ?>
        <p>
            <input type="checkbox" id="<?php echo $slug_anwalt; ?>" name="<?php 
                echo $slug_anwalt; ?>" value="yes" <?php 
                checked( get_post_meta( $post->ID, $slug_anwalt, true ), 'yes' ); 
                ?>><label for="<?php echo $slug_anwalt; ?>"><?php 
                echo $titolo_anwalt; ?></label>
        </p>
        <?php
    endwhile;
}

function anwaelte_add_meta_box() {
    add_meta_box(
        'anwaelte-meta-box',
        'Autor festlegen',
        'anwaelte_display_meta_box',
        'insights',
        'side',
        'low'
    );
}
add_action( 'add_meta_boxes', 'anwaelte_add_meta_box' );

function anwaelte_user_can_save( $post_id, $nonce ) {
    $is_autosave = wp_is_post_autosave( $post_id );
    $is_revision = wp_is_post_revision( $post_id );
    $is_valid_nonce = ( isset( $_POST[ $nonce ] ) && wp_verify_nonce( $_POST[ $nonce ], 
        plugin_basename( __FILE__ ) ) );

    return ! ( $is_autosave || $is_revision ) && $is_valid_nonce;
}

function anwaelte_save_meta_box( $post_id ) {
    global $loop_anwaelte;
    foreach ( $loop_anwaelte as $anwalt ) {
        if ( anwaelte_user_can_save( $post_id, $anwalt ) ) {
            if ( isset( $_POST[ $anwalt ] ) ) {
                update_post_meta( $post_id, $anwalt, $_POST[ $anwalt ] );
            } else {
                delete_post_meta( $post_id, $anwalt );
            }
        }
    }
}
add_action( 'save_post', 'anwaelte_save_meta_box' );

My second problem is that I have no idea how I can load and display the checked posts (anwaelte) in the insight-custom post. Will I have to use a loop again?

0

When you submit the form there is a new request to the server. Because global $loop_anwaelte; is populated on add_meta_box it will not be populated on save_post which fires much, much earlier in the new page load. I am pretty sure that is why your "save" isn't working. The foreach ( $loop_anwaelte as $anwalt ) simply does nothing, and if you had debugging enabled you'd likely see errors/warnings.

There are several ways to solve this:

  1. Populate the array twice, once on save and once on the meta box display
  2. Populate the global early in the page load, for example, on one of the load-{page_hook} hooks
  3. Better, use option #2 and convert the whole code base into a class to avoid the global altogether.
  4. Rewrite your form so that you are passing an array through $_POST that you can then iterate over.

Option 1) is inefficient for obvious reasons.

Options 2) and 3) are prefered, with 3) being much, much neater.

Option 4) would have validation concerns to deal with as $_POST data-- all $_POST data including the key names-- is subject to user manipulation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.