0

I have added a custom metabox for authors where they can fill in a url to a source, which I can then use in my template.

In my functions.php

<?php
/* Add metaboxes (see below) */
function add_custom_metaboxes(){
    add_meta_box('source_post_metabox', 'Link to bron (optional)', 'output_source_metabox', 'post');
}
add_action('add_meta_boxes', 'add_custom_metaboxes');

/* Save values of custom metaboxes on save */
function save_custom_metabox($post_id){

    if(!isset($_POST['source_post_metabox_nonce'])) :
        return;
    endif;

    if(!wp_verify_nonce( $_POST['source_post_metabox_nonce'], 'source_post_metabox')) :
        return;
    endif;

    if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) :
        return;
    endif;

    if(!current_user_can('edit_post', $post_id)) :
        return;
    endif;

    if ( isset( $_POST['source_post'] ) ) {
        $data = sanitize_text_field( $_POST['source_post'] );
        update_post_meta( $post_id, '_post_source', $data );
    }

}
add_action('save_post', 'save_custom_metabox');

function output_source_metabox($post){
    wp_nonce_field('source_post_metabox', 'source_post_metabox_nonce');
    $post_source = $post->_post_source;

    echo '<label for="source_post">';
    echo '<input type="text" id="source_post" name="source_post" value="'.$post_source.'" style="width: 80%;max-width: 720px;">';
    echo ' Source of your post</label>';
    echo '<p>Try to be as specific as possible. <br> E.g. <em>http://tweakers.net/nieuws/101372/ing-belgie-wil-betalingsgedrag-van-klanten-meer-gebruiken-voor-dienstverlening.html</em></p>';
}

?>

However, I want to add the option to add multiple sources. I thought about it, and the most user-friendly seems to add a button that adds an input field to the metabox. Something like this: http://jsfiddle.net/BramVanroy/23n6s717/

counter = 0;
$(".add-field").click(function() {
    counter++;
    $("#source_post").after('<input type="text" id="source_post_'+counter+'" name="source_post_'+counter+'" value="" style="width: 80%;max-width: 720px;">');
});

However, I don't know how I can "link" these new input fields to my back-end. How can I let Wordpress know that there are multiple fields that need to be accounted for, and saved? And how can I output all of them?

  • 2
    This is really just PHP and HTML. Use source_post[] and process the $_POST data as array. – s_ha_dum Apr 9 '15 at 17:22
  • @s_ha_dum Could you give me a hand putting that into code? – Bram Vanroy Apr 9 '15 at 17:46
1
+50

I packed everything together. Consider using wp_enqueue_script() to use the script. With this code, you will save all URLs as an array. See how I use get_post_meta() to retrieve the saved URLs.

function save_custom_metabox($post_id){
    if(!isset($_POST['source_post_metabox_nonce'])) :
        return;
    endif;

    if(!wp_verify_nonce( $_POST['source_post_metabox_nonce'], 'source_post_metabox')) :
        return;
    endif;

    if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) :
        return;
    endif;

    if(!current_user_can('edit_post', $post_id))
        return;


    if ( isset( $_POST['source_post'] ) ) {
        foreach( $_POST['source_post'] as $key => $val )
            $_POST['source_post'][ $key ] = sanitize_text_field( $val );
        update_post_meta( $post_id, '_post_source', $_POST['source_post'] );
    }

}
add_action('save_post', 'save_custom_metabox');

function output_source_metabox($post){
    wp_nonce_field('source_post_metabox', 'source_post_metabox_nonce');
    $post_sources = get_post_meta( $post->ID, '_post_source', true );
    if( is_array( $post_sources ) )
        foreach( $post_sources as $post_source )
            echo '<input type="text" id="source_post" name="source_post[]" value="'.$post_source.'" style="width: 80%;max-width: 720px;"><br />';
    else
        echo '<input type="text" id="source_post" name="source_post[]" value="" style="width: 80%;max-width: 720px;"><br />';
    echo '<button class="add-field">+</button>';
    echo '<p>Try to be as specific as possible. <br> E.g. <em>http://tweakers.net/nieuws/101372/ing-belgie-wil-betalingsgedrag-van-klanten-meer-gebruiken-voor-dienstverlening.html</em></p>';
    echo '<script>counter = 0;
jQuery(".add-field").click(function( event ) {
    event.preventDefault();
    counter++;
    jQuery("#source_post").after(\'<input type="text" id="source_post_\'+counter+\'" name="source_post[]" value="" style="width: 80%;max-width: 720px;">\');
});</script>';
}

Usage in template files

You can output these URLs in template files like this:

<?php
//We expect $post_sources to be an array
$post_sources = get_post_meta( get_the_ID(), '_post_source', true );
if( ! empty( $post_sources ) && count( $post_sources ) > 0 ):
    //Output all sources as a list if sources exist
    ?>
    <ul><?php
    foreach( $post_sources as $post_source ):
    ?>
        <li><?php echo $post_source; ?></li>
    <?php
    endforeach;
    ?>
    </ul>
<?php endif;


if( isset( $post_sources[ 0 ] ) ):
    //Output only a single source, in this case the first one
    ?>
    <p><?php echo $post_sources[ 0 ]; ?></p>
    <?php
endif;
?>
  • Thanks, this looks promising! (Not tested yet.) Could you give an example how I would output this in a template file? Only one element from the array, as well as all of them? – Bram Vanroy Apr 13 '15 at 11:04
  • updated my answer :) – websupporter Apr 13 '15 at 11:14
  • Does this mean that you only need one nonce field per metabox? I always thought you would need one per input field? – Bram Vanroy Apr 15 '15 at 6:02
  • One is enough :) – websupporter Apr 15 '15 at 8:10

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.