Meta box controls – checkbox and radio buttons

Image showing a list with a checkbox

I already made a tutorial about meta boxes. In the tutorial I covered color picker control, and a cross between repeater field and related pages control. It was pointed out to me that I should cover as much of the controls that can be placed in a meta box as possible. So I wrote some of them down and thought to myself – here are nice 3 or 4 articles I can write! Cool. And then I was swamped with other stuff I have going on and I just couldn’t get myself to sit down and write an article.
But I finally found some time so here we are :)

Notice: This article was written in 2016. WordPress has changed a lot since then, so take this article with a grain of salt…

The first article in the series will cover radio boxes and check boxes. They might seem like an easy thing to add, but they can be tricky. I’ll also put a simple input field in, for a good measure. Let’s get started.

Prerequisites

I’ll be placing my code in functions.php file, because of the convenience. But you can easily add the code in a separate php file that you’ll include through your functions.php file. First we need to use the add_meta_box() function. We are going to hook to add_meta_boxes action

add_action( 'add_meta_boxes', 'mytheme_add_meta_box' );

if ( ! function_exists( 'mytheme_add_meta_box' ) ) {
	/**
	 * Add meta box to page screen
	 *
	 * This function handles the addition of variuos meta boxes to your page or post screens.
	 * You can add as many meta boxes as you want, but as a rule of thumb it's better to add
	 * only what you need. If you can logically fit everything in a single metabox then add
	 * it in a single meta box, rather than putting each control in a separate meta box.
	 *
	 * @since 1.0.0
	 */
	function mytheme_add_meta_box() {
		add_meta_box( 'additional-page-metabox-options', esc_html__( 'Metabox Controls', 'mytheme' ), 'mytheme_metabox_controls', 'page', 'normal', 'low' );
	}
}Code language: PHP (php)

As a precaution, we are wrapping it all up in a function_exists() check. Inside the function you can add as many meta boxes as you want to. In the function you’ll add the unique meta box id (additional-page-metabox-options), the name of the meta box (esc_html__( ‘Metabox Controls’, ‘mytheme’ )), the callback function that will actually render the meta box (mytheme_metabox_controls), whether you’ll like to put the metabox on the page or post screen (here we are adding one on the page screen), the context and priority of it (normal and low).

Now that we have that we can add the callback function.

Adding the controls

In the callback function that we defined in the add_meta_box() function we will add our HTML that will render the controls. In our case these will be simple input types – text, radio box and checkbox. We can also style them as we see fit. But where are we actually saving these settings? Well since everything in WordPress is based around post types – the post is just post post type, page is a different post type, navigation as well and we can make our own custom post types, we are ‘binding’ our meta box controls to every single post. So every post can have different controls checked out or not. We can add an input field, or a textarea in the same manner, that will show some small intro or info of our posts or pages. Every post or page will have its own different info text. This is done by creating a post meta. So every control is a certain post meta data that we attach to our posts or pages.

This is why we will define variables that will check if the post data, for a certain control, exists or not. That way when we save the post data, we can immediately see it selected (or written) in our custom fields in the meta box.

if ( ! function_exists( 'mytheme_metabox_controls' ) ) {
	/**
	 * Meta box render function
	 *
	 * @param  object $post Post object.
	 * @since  1.0.0
	 */
	function mytheme_metabox_controls( $post ) {
		$meta = get_post_meta( $post->ID );
		$mytheme_input_field = ( isset( $meta['mytheme_input_field'][0] ) && '' !== $meta['mytheme_input_field'][0] ) ? $meta['mytheme_input_field'][0] : '';
		$mytheme_radio_value = ( isset( $meta['mytheme_radio_value'][0] ) && '' !== $meta['mytheme_radio_value'][0] ) ? $meta['mytheme_radio_value'][0] : '';
		$mytheme_checkbox_value = ( isset( $meta['mytheme_checkbox_value'][0] ) &&  '1' === $meta['mytheme_checkbox_value'][0] ) ? 1 : 0;
		wp_nonce_field( 'mytheme_control_meta_box', 'mytheme_control_meta_box_nonce' ); // Always add nonce to your meta boxes!
		?>
		<style type="text/css">
			.post_meta_extras p{margin: 20px;}
			.post_meta_extras label{display:block; margin-bottom: 10px;}
		</style>
		<div class="post_meta_extras">
			<p>
				<label><?php esc_attr_e( 'Input text', 'mytheme' ); ?></label>
				<input type="text" name="mytheme_input_field" value="<?php echo esc_attr( $mytheme_input_field ); ?>">
			</p>
			<p>
				<label>
					<input type="radio" name="mytheme_radio_value" value="value_1" <?php checked( $mytheme_radio_value, 'value_1' ); ?>>
					<?php esc_attr_e( 'Radio value 1', 'mytheme' ); ?>
				</label>
				<label>
					<input type="radio" name="mytheme_radio_value" value="value_2" <?php checked( $mytheme_radio_value, 'value_2' ); ?>>
					<?php esc_attr_e( 'Radio value 2', 'mytheme' ); ?>
				</label>
				<label>
					<input type="radio" name="mytheme_radio_value" value="value_3" <?php checked( $mytheme_radio_value, 'value_3' ); ?>>
					<?php esc_attr_e( 'Radio value 3', 'mytheme' ); ?>
				</label>
			</p>
			<p>
				<label><input type="checkbox" name="mytheme_checkbox_value" value="1" <?php checked( $mytheme_checkbox_value, 1 ); ?> /><?php esc_attr_e( 'Checkbox value', 'mytheme' ); ?></label>
			</p>
		<?php
	}
}
Code language: JavaScript (javascript)

First we need to fetch all the post meta values for the current post. Then we define our variables that we’ll use in our HTML below. And remember: every time you create a meta box, you need to include a nonce. They are security measure that will prevent any possible malicious tempering with the fields. Next we create our controls. You can see the previously defined variables – in the input field I’ve escaped the text using esc_attr() function, if you wish to include any kind of HTML, I recommend the wp_kses_post() function, since esc_attr() strips all the html out.

For the radio boxes and checkbox we are using WordPress built in checked function.

Saving the meta boxes

We have our meta boxes ready, but we still need to save the values within our inputs. For that we need to hook into save_post hook. This hook fires any time a post or a page is saved, so we are using that to our advantage.

add_action( 'save_post', 'mytheme_save_metaboxes' );

if ( ! function_exists( 'mytheme_save_metaboxes' ) ) {
	/**
	 * Save controls from the meta boxes
	 *
	 * @param  int $post_id Current post id.
	 * @since 1.0.0
	 */
	function mytheme_save_metaboxes( $post_id ) {
		/*
		 * We need to verify this came from the our screen and with proper authorization,
		 * because save_post can be triggered at other times. Add as many nonces, as you
		 * have metaboxes.
		 */
		if ( ! isset( $_POST['mytheme_control_meta_box_nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['mytheme_control_meta_box_nonce'] ), 'mytheme_control_meta_box' ) ) { // Input var okay.
			return $post_id;
		}

		// Check the user's permissions.
		if ( isset( $_POST['post_type'] ) && 'page' === $_POST['post_type'] ) { // Input var okay.
			if ( ! current_user_can( 'edit_page', $post_id ) ) {
				return $post_id;
			}
		} else {
			if ( ! current_user_can( 'edit_post', $post_id ) ) {
				return $post_id;
			}
		}

		/*
		 * If this is an autosave, our form has not been submitted,
		 * so we don't want to do anything.
		 */
		if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
			return $post_id;
		}

		/* Ok to save */

		if ( isset( $_POST['mytheme_input_field'] ) ) { // Input var okay.
			update_post_meta( $post_id, 'mytheme_input_field', sanitize_text_field( wp_unslash( $_POST['mytheme_input_field'] ) ) ); // Input var okay.
		}

		if ( isset( $_POST['mytheme_radio_value'] ) ) { // Input var okay.
			update_post_meta( $post_id, 'mytheme_radio_value', sanitize_text_field( wp_unslash( $_POST['mytheme_radio_value'] ) ) ); // Input var okay.
		}

		$mytheme_checkbox_value = ( isset( $_POST['mytheme_checkbox_value'] ) && '1' === $_POST['mytheme_checkbox_value'] ) ? 1 : 0; // Input var okay.
		update_post_meta( $post_id, 'mytheme_checkbox_value', esc_attr( $mytheme_checkbox_value ) );

	}
}
Code language: PHP (php)

First we need to check our nonce. If the nonce check fails, we won’t save the meta data. The //Input var okay. comment at the end is for code sniffer purposes. After that we are checking if the user has permissions to save the post (page). Also we do not want to save our meta data on auto save. WordPress will periodically, unless we disable it, make an auto save of our post (for recovery purposes). The DOING_AUTOSAVE constant will be defined true within the wp_autosave() function.
After all the checks have passed we can save our post meta. Always sanitize your input values – post meta gets written to the post_meta table in our database, so we want to make sure no malicious code can get in there. Likewise we are always escaping on the output – to prevent any malicious code being outputted on our page.
For the checkbox we first need to see if the POST variable is defined and set to 1, so that we can put that in the variable that will be placed as a value of our post meta for the checkbox. Checkboxes are a bit different because if the checkbox input isn’t checked, on the form submit it looks like it doesn’t exist. That’s why we are using this intermediate step with our variable – we want to put either 0 or 1 in the post meta for the checkbox control so that we can use it in our theme.

With the minimal amount of styling our meta box looks like this

Meta box custom controls
Our custom defined meta box controls ready to be used

Using the controls

We have our controls, they can be saved, so we want to use them, right?

Well it’s actually really easy. All you need to use is the function get_post_meta(). In it you need to specify the post id from which you want to get the saved meta data, you can specify the exact post meta to fetch, and you can choose if you want to return the single value or not

get_post_meta( int $post_id, string $key = '', bool $single = false )Code language: PHP (php)

The post meta is usually fetched within the loop, so all you need to use is the built in get_the_ID() function. In the case of our input field the correct code will be

$input_text = get_post_meta( get_the_ID(), 'mytheme_input_field', true );Code language: PHP (php)

Mind you that we are within the loop. You can use it outside of it, but you’ll need to fetch the post ID somehow. So to actually use the text the best thing to do is to make a check if it’s not empty and if it’s set

if ( isset( $input_text ) && '' !== $input_text ) {
	echo esc_attr( $input_text );
}Code language: PHP (php)

The same would apply to our radio and checkbox fields, with the exception that you’d be checking if the value of the checkbox meta data is not 0 (or is equal to 1).

And that is it for the start of the meta box controls tutorial, I hope you find it useful. If you have any questions feel free to ask it in the comments below, and as always, happy coding :)

20 responses

  1. I have used your code on my function file, but it’s not displaying on my post page backend.

    1. Hi. I have edited your post. No need to use all caps. that usually means shouting on the internet :D

      This post is from 2016, and it should be checked to see if there are any errors in the current WP versions. Do you get any errors in the debug log?

  2. Oh, I figured it out. I was looking on a post edit screen. The code creates the meta boxes on a page.

    1. COol :) You can change where the metabox renders. It can be post, page or CPT

  3. I added the contents of the three largest boxes to a functions.php file and nothing happened on my site. Am I missing something here?

    1. DO you have any errors? Does the meta box appear in the admin area? It could be hidden. You can check the Screen Options at the top and see if it’s there (a checkmark).

  4. […] Last time I covered the input field, radio buttons and check boxes for your meta box custom controls. We are going to continue on the same path. Today we’ll be interested in adding select dropdowns in our meta box. The environment in which we are going to do this will be the same as last time, so if you are testing this out, simply add the new controls after the already existing ones, and you’ll be good to go. […]

  5. Hi there, thanks for the post, it is really very helpful. I do Have a question though, you mentioned:

    “The same would apply to our radio and checkbox fields, with the exception that you’d be checking if the value of the checkbox meta data is not 0 (or is equal to 1).”

    How exactly would you do that?

    1. Well when you want to make a check for $input_text = get_post_meta( get_the_ID(), 'mytheme_input_field', true ); you need to check for if ( isset( $input_text ) && 1 == $input_text ) {

      The easiest way to see what you need to check against is to try to print out the value of the meta field print_r( $input_text, true ); For the checkbox field the value will either be nothing (unchecked), or the value you have set in the checkbox input value (this can be arbitrary), since the checkbox work in the way that if the input checkbox field is checked the input’s $_POST will exist, and if it’s not checked it won’t. So in that case, if you haven’t got anything checked, nothing will get written in the postmeta table ;)

      Hope this helps :)

      1. OK so in your example, you have three radio fields (Im going off the metabox image above): Radio value 1, Radio value 2, Radio value 3.

        Let’s say Radio value 1 had a value of “button_one_selected” and when the user selected Radio value 1 they were shown the following text: “You selected Radio value 1”

        My question is this:

        How would you do that? What is the code you would use to do that?

        See I am trying to understand how to use radio fields in a metabox but I have not gotten a straight answer anywhere, from anyone. I don’t understand why its so hard to explain or give an answer to. If you could help me to understand that would be AWESOME!

        Thanks again for the tutorial.

        1. Not 100% sure I understand you correctly. The above code in the article will produce the image in the article (with the radio inputs).

          mytheme_radio_value is the name of the radio input fields (has to be the same for the entire radio group). I’m not sure I understand where do you want to show the text “You selected Radio value 1”. As an alert popup, or? Because if you want to do that dynamically, you’ll need to add additional JavaScript.

          1. OK so the radio fields in the image above each have a value correct?

            Radio value 1 = value_1

            Radio value 2 = value_2

            Radio value 3 = value_3

            So what are they for? Looks? what do you use them for? How would you use the value of one of the fields chosen?

            That’s what I am asking if some one chose the first radio field how would you display something in the theme, anywhere, it doesn’t matter?

            It’s easy to explain how to create a metabox but I guess its hard to make a working example or show an example of how to actually use it.

          2. Sorry I meant to say show “You selected Radio value 1” on the front end when the Radio value 1 is clicked and the post is saved , not in the admin area.

          3. Oh now I understand. Sure, the saved meta value for that post/page where you put the metabox (in the case of the article it’s the page), will equals the value of that field.

            For example, you have a page with the above code and you select the third radio value (Radio value 3), then you go to your page template and if you put

            $input_text = get_post_meta( get_the_ID(), 'mytheme_radio_value', true );

            print_r('

            ');
            print_r( $input_text );
            print_r('

            ');

            The output on the page will be value_3

            This can be then used if you want to make a certain condition happen based on the selected radio value – for instance if you want to create a separate section with image, and you use the radio buttons to align the image left, right or centre (a trivial example but can be used in this manner). Then you could go to the page template that displays your page and say

            if( $input_text === 'value_1' ) {
            // align image to the left
            } elseif ( $input_text === 'value_2' ) {
            // align the image to the right
            } else {
            // align the image centre
            }

            Now this is just an example how you could use it (I mean, the last radio button in this example isn’t really necessary since you have a fallback else condition and you’d label the values more sensible, like left_align and right_align for instance). But the gist is there :)

            Hope this clarifies the issue. You can also use this to actually display the value (but that’s less likely and I wouldn’t do it imo).

          4. Note: I had to use to escape pre tags since disqus is using them so I had an odd looking code part :D

          5. no worries, I understand.

          6. AWESOME!!! Thank you sir, that helped tremendously. Best answer I have gotten by far from anyone, anywhere!!!.

            Thanks again for the answer and for the help.

  6. sonia maklouf Avatar
    sonia maklouf

    Thanks for this tuto Denis. Glad that you find the time to write this :-D
    Have you plan to talk about numeric slider in your next articles ?

    1. What do you mean numeric slider? I plan to cover a lot more controls in the next few articles. If you are reffering to jqueryUI slider than yes, I can do a tutorial on that as well (I already have calendar in plans)

      1. sonia maklouf Avatar
        sonia maklouf

        Yes by numeric slider I mean jqueryUI slider with custom handle : https://jqueryui.com/slider/#custom-handle

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.