Custom Meta Boxes

See the CMB Wiki for a full description and examples. If you have any issues or feature requests, please post them in the issues section. I’ve closed the comments here.

When using WordPress as a CMS, you’ll often need to associate data with a post or page that doesn’t fit the predefined inputs (title, post editor, categories…). WordPress has a built-in feature called “Custom Fields” for managing this data, but the interface isn’t user-friendly.

Custom Meta Boxes allow you to build clean, understandable interfaces for entering metadata. I use them on almost every project. Above is a screenshot of my CRM which makes extensive use of metaboxes (full screenshot).

You could use a plugin like More Fields to create them, but I prefer to have them included in the theme rather than dependent on a plugin.

Here’s how to set up your own meta boxes:

  1. Download a copy of our metabox code from GitHub
  2. Create a “lib” directory in your theme or child theme, and a “metabox” directory inside “lib”. Upload the files you downloaded above into /wp-content/themes/your-theme/lib/metabox
  3. Include /lib/metabox/init.php in your functions.php file, and define your metaboxes in an array (see below).

Here’s an example of using the metabox code to create a Rotator Options metabox that’s displayed on the Rotator post type. This is what I use when installing the WP Rotator plugin.

Each meta box is stored as an array. There’s a ton of field options, including text, textarea, checkbox, dropdown list, and WYSIWYG. For examples on how to use all the fields, look at /metabox/example-functions.php.

chat129 Comments

  1. says

    Hey Bill,

    My intention is to use this on a Genesis Child theme, but I think I’m missing a step.

    I included this line in my child theme functions.php file:
    require_once(CHILD_DIR.’/lib/metabox/init.php’);

    Warning: Invalid argument supplied for foreach() in /home/mysite/public_html/mydomain.com/wp-content/themes/endeavor/lib/metabox/init.php on line 35

    Line 35 of init.php contains this line: (some syntax removed for commenting purpose)

    cforeach ( $meta_boxes as $meta_box ) {

    Any idea what could be causing this? My editor page still loads, but with no meta boxes from example-functions.php

    • Bill Erickson says

      Are you sure you formatted your $meta_boxes[] array correctly? Can you try it using the code I provided above (if you don’t have a “rotator” post type change it to ‘pages’ => array(‘post’) )

  2. says

    Yay! Working now.

    First of all, I was being dense and didn’t create a proper function for this in my functions.php file…der!

    Second, your test sent me in the right direction as I did get the Rotator function to show in my post editor.

    Third, I grabbed all of the functions from the example-functions.php file and they didn’t show. Looking through the example functions, I had to change:
    ‘pages’=>array(‘pages’) to ‘pages’=>array(‘posts’). Then the extra metaboxes appeared in my post editor:)

    Thanks for your guidance, and to all of you for the cool code!

    One follow up if I may. Would I need to create a separate register post type function in order to show these meta boxes on only that post type? Then simply change the post type above?

    Or do I need to create the custom post type within the above function?

    Please excuse my naivety, I’m still learning CPTs…

    • Bill Erickson says

      In my “genesis-child” theme (the base theme I build everything from), I have one function that registers post types, one for taxonomies, and one for meta boxes ( this one). So you would just need to register the post type somewhere (not necessarily in this function) and then the pages(‘post-type’) will work.

      Also keep in mind that you can have as many meta boxes as you like in this one function. Just do

      $meta_boxes = array();
      $meta_boxes[] = array(

      );
      $meta_boxes[] = array(

      );

  3. says

    Great, thanks for the clarification, once I get this down, the sky is the limit;)

    Since I posted the above I researched some CPT tutorials and copy/pasted the CPT code. It didn’t work. While testing, I copied in a duplicate CPT and renamed the variables. Then my new one showed up, but not the original example.

    After some further finagling I’m convinced something strange is happening, it’s probably so simple I’m missing it, but I can duplicate this behavior consistently….

    …I have two CPTs registered in functions.php. Both are exactly the same except that I have changed the names of the labels. Only the second one listed in functions.php shows in my admin menu. When I remove the one on top, then the CPT disappears from my admin area. When I put it back, again, only the second CPT registered shows up in admin. If I switch the two around…again, whatever CPT is lowest in my functions.php is registered and showing.

    I have looked for any differences and I don’t see any!

    I know this is beyond the scope of your post here, so feel free to ignore my ranting here, but if you have any thoughts of what would cause such a thing, I’m all ears.

    Here are the functions as they appear in my functions.php file in my Genesis child theme: http://snipt.org/wpgoi

    Thanks for your code and help already given:)

    • Bill Erickson says

      I dropped that code in my functions.php file and it worked just fine – both post types showed up. Maybe it’s an issue with some other code in your functions file?

  4. says

    @adam you should be able to use the Custom Meta Boxes with any post types, including ones you or a plugin create. Just plugin in the CPT slug into the array :)

  5. says

    Bill,
    I think this is great and I love the way it works!

    One question that I haven’t been able to find and answer for, and I apologize for my lack of know-how, but how to I call this information to get it to show up on a post page? I am able to customize the functions and it all shows up on the back end as I planned. I just can’t figure out how to get my “project_text” or anything else to show up on a page. Can you provide me with a sample php to call this info?

    Am I going about this wrong:
    ID, ‘project_text’, true); ?>

    Thank you sir!

    And here is my functions to see if they are correct:

    add_action( ‘init’ , ‘be_create_metaboxes’ );
    function be_create_metaboxes() {
    // Include & setup custom metabox and fields
    $prefix = ‘cmb_';
    $meta_boxes = array();

    $meta_boxes[] = array(
    ‘id’ => ‘project_statistics’,
    ‘title’ => ‘Project Statistics’,
    ‘pages’ => array(‘post’), // post type
    ‘context’ => ‘normal’,
    ‘priority’ => ‘high’,
    ‘show_names’ => true, // Show field names on the left
    ‘fields’ => array(
    array(
    ‘name’ => ‘Project Stats’,
    ‘desc’ => ‘Enter the stats for this project below’,
    ‘type’ => ‘title’
    ),
    array(
    ‘name’ => ‘Main Project Image’,
    ‘desc’ => ‘Upload more project images or enter an URL.’,
    ‘id’ => $prefix . ‘main_project_image’,
    ‘type’ => ‘file’
    ),
    array(
    ‘desc’ => ‘field description (optional)’,
    ‘id’ => $prefix . ‘project_text’,
    ‘type’ => ‘wysiwyg’
    ),
    array(
    ‘name’ => ‘More Project Images’,
    ‘desc’ => ‘Upload more project images or enter an URL.’,
    ‘id’ => $prefix . ‘more_project_images’,
    ‘type’ => ‘file’
    ),
    )
    );
    require_once(TEMPLATEPATH . ‘/lib/metabox/init.php’);
    }

    • Bill Erickson says

      Just use something like this:

      < ?php
      global $post;
      $project_text = get_post_meta($post->ID, ‘project_text’, true);
      echo $project_text;
      ?>

      • says

        Bill,
        I had located something very similar before you responded, so I wasn’t that far of, However even with your suggested php I still have not been able to get this to work. I even tried it on the “twentyten” theme and have had absolutely no luck at getting anything to show up.

        I can add and remove all day from the admin/editor by modifying the functions, I just can’t get that data to populate to the live post page. Am I missing something. Do I need to register something else in the functions?

        What you have created is so clean and awesome, I’d love to be able to use it but I don’t see how. Thank You!

        -charlie

        • Bill Erickson says

          I’d have to see your code to see what’s wrong, but there’s a few possible causes:

          – You’re forgetting to put global $post; before using $post->ID in the get_post_meta() function.
          – You’re using the wrong meta_key. add the_meta(); to your theme (inside the loop) to list all metadata
          – There’s an issue with your metabox that prevents the data from saving. You’d know if this was happening though, because after you click “Save” you wouldn’t see the post.

          Either run the_meta(); in the loop or turn on custom fields for that post to look at all the meta data. Make sure you’re calling the right field name, and that you use global $post;

          • says

            AHA!
            putting the_meta() in the loop is what did it for me. This opens up a whole nother can of worms to work with. I appreciate the shove in the right direction!

          • says

            One other thing that was throwing me off was the prefix included in the functions you provide. So in my code ‘project_text’ has to be ‘cmb_project_text’ as well as any other instances using the custom meta boxes. I assume there is a rhyme or reason, but are the prefixes actually needed? It would seem easier/shorter without.

            Again, please forgive my lack of knowledge just wanted to post my additional findings in attempt to help others. Thanks!

  6. Bill Erickson says

    @ Charlie, it’s a recommended coding practice in WordPress to prefix everything. If you install a plugin or theme that uses the custom field “project_text” you could have some bad interactions. By creating your own prefix you minimize the chances of using the same field name (what’s the chance someone created a field called be_project_text or crm_project_text).

  7. says

    Hey Bill,
    First of all thank you for this great plugin/code.

    I just installed it on one of my themes and it works great.
    I do have one question.
    I created a field (‘type’ => ‘textarea’) and I need to add some HTML code in the textarea and I need the html code to do something in the front end. However, the code gets displayed in text-format.

    Example:
    I have the following ul list

    item 1
    item 2
    item 3

    I need this to be displayed as an unordered list in the front-end. But what I get is the code displayed in text-format.

    I know I have the option of changing the field type to ‘wysiwyg’, but I need to create several custom fields in “page” view and I would prefer if they were ‘textarea’ instead of ‘wysiwyg’.

    Please let me know if this is possible and if yes, how would I go about doing it.

    Thank you in advance.

    Best,
    Artin H.

    • Bill Erickson says

      When rendering it on the frontend, you’ll have to use the html_entity_decode() function. Ex:

      $embed = get_post_meta($post->ID, ‘embed’, true);

      echo html_entity_decode( $embed );

  8. says

    Hey Bill,
    I’ve been using your code and it’s working great. Thank you very much.
    I do have one question. In one of my themes, I have added a ‘Radio button’ with two values: Yes/No

    array(
    ‘name’ => ‘Radio inline’,
    ‘desc’ => ‘Please choose Yes or No’,
    ‘id’ => $prefix . ‘test_radio’,
    ‘type’ => ‘radio_inline’,
    ‘options’ => array(
    array(‘name’ => ‘Yes’, ‘value’ => ‘Yes’),
    array(‘name’ => No’, ‘value’ => ‘No’),
    )
    ),

    How would I check for the value?
    Depending on the value, I’m going to either show something or not.

    Here is how do the an if/else statement when it’s a regular field or a textarea:

    if ( get_post_meta($post->ID, ‘cmb_xyz’, true) ) :
    echo get_post_meta($post->ID, “cmb_xyz”, true);
    endif;

    But I’m not sure how to check for the value of a radio button.

    If the value is “Yes” show this
    else show nothing

    Thank you in advance.

    Best,
    Artin H.

    • Bill Erickson says

      To answer your specific question, you would do it like this:


      $test_radio = get_post_meta($post->ID, 'test_radio', true);
      if ($test_radio == 'yes')
      echo 'Yes';
      elseif ($test_radio == 'no')
      echo 'No';

      Instead of using a radio with Yes or No, I’d rather use a checkbox. Then you could just check to see if the custom field has a value.

  9. says

    Bill,
    Just curious, I’ve been really enjoying the Custom Meta Boxes, but noticed that the ‘wysiwyg’ option is a little more limiting than the WordPress default where you can insert an image within the text and/or toggle the HTML view. I understand why you would do this, but is there a meta box option that could would include these like the wordpress?

    Thanks.

    • Bill Erickson says

      I don’t think it’s possible to duplicate the WordPress post editor with the media library. Even if you could add the media library to the alternate WYSIWYG, it would require some serious customizations to the media library to make the image not automatically inserted into the main post editor instead of your alternate one.

      If you need the full WordPress editor I’d recommend finding a way to use just the post editor instead of an additional WYSIWYG. For instance, if you’re trying to do multiple content columns, use a content filter or shortcode.

  10. trish says

    thanks so much for this! I love how elegantly it works. I have a question though. I’ve created two custom fields, one for first name & one for last name. I’ve also hidden the post title from the editor. Now I would like to combine the first name & last name fields to give me the post title, such that it would replace WP’s post title field. (Right now, the way I have it set with the post title field hidden in the editor, I am getting ‘Auto Draft’ in the listings in the admin.) I think I need to set up another field that combines both the first name & last name but I’m unsure how that would be set up in the function with the arrays or how it would insert into the Post Title field. Does that make sense? Thanks again!

      • Bill Erickson says

        It’s beyond the scope of this post, but there should be a way to hook into the post title when the post is saved (hook = save_post) and use your post meta like this:
        $title = $first .’ ‘. $last;

        • trish says

          Thanks so much for pointing me to the right direction. For any of your readers who may be interested in the solution, this is what worked for me:

          add_filter(‘title_save_pre’, ‘save_new_title’);
          function save_new_title($people_title) {
          if ($_POST['post_type'] == ‘people_profiles’) :
          $fname = $_POST['_fname'];
          $lname = $_POST['_lname'];
          $fnamelname = $fname.’ ‘.$lname;
          $people_title = $fnamelname;
          endif;
          return $people_title;
          }

          I really appreciate your help and the custom metaboxes!!

          • Steven Querry says

            Hello Trish,

            I would love to be able to accomplish this as well. However I’m new to all of this. I have 5 meta boxes I would like to put together to make the title. I think I’m following along till you get to the first $fname. Could you provide further? I tried this with no luck to start:

            add_filter(‘title_save_pre’, ‘save_new_title’);

            function save_new_title($vehicle_title) {
            
if ($_POST['post_type'] == ‘vehicle’) :

            $vehicle_year = $_POST['vehicle_year'];

            $vehicle_color = $_POST['vehicle_color'];

            $vehicle_yearvehicle_color = $vehicle_year.’ ‘.$vehicle_color;

            $vehicle_title = $vehicle_yearvehicle_color;
            
endif;
            
return $vehicle_title;

            }

            In my create metaboxes action I have a prefix of “sq_” – does that need to be included in the above script? Also where does this add_filter go? Does it need to be nested with my create_metaboxes or create_my_post_types?

            Thank you so much for you help…

          • Bill Erickson says

            I’m sorry, I don’t have any experience editing the title on save so I can’t help. But why edit it there? Allow the user to construct the title however they want and then on the frontend add the vehicle year and color before displaying the title.

  11. trish says

    Hi Bill,

    I have another question regarding the image file upload field. I don’t know if I’m doing something wrong but it doesn’t seem to be working. I’ve got the other fields set up correctly and are being entered and saved properly. I didn’t do anything but copy and paste the code from example-functions file. The field itself is showing up in the editor; the issue is that when I click on ‘Upload File’ button, nothing happens. Am I missing something? I’m working off my localhost so I don’t know if that has something to do with it.

    Thanks again!
    Trish

        • Bill Erickson says

          I’m out of the country so haven’t been keeping up with the CMB development, but my understanding is that it isn’t working at the moment. What I would use is the default media uploader, then once uploaded copy the image url and paste it in a text field.

          • Mike says

            Well I think I found one senario:

            If you name your theme like “My Theme”, it is not posible to access the jquery.cmbScripts.js file and you will get a 403 message.

            Name your theme always without spaces, remove the space or use underscore: “MyTheme” or “My_Theme”, because it’s space sensitive!

            Good Luck ;-)

    • Bruce says

      Trish,
      Did you ever find a solution to the image file upload field?
      I have the exact same issue. I too am running on localhost (XAMPP).
      I have discovered in Firebug that there is a 403 access error on the file – jquery.cmbScripts.js?ver=3.1.3.
      I have emailed Jared and am trading emails with him now on it
      Thanks

  12. Danny G Smith says

    Anyway, I need to have multiple uploads, and it looks like the are being stored as a two dimensional array in the meta fields so it should be possible, but I am not sure how to get it to work in the front-end. is there something that is intuitive that I am missing? The way I am doing it is uploading the file first using the upload box, coping the url, pasting it in the box again, and then it is there below with links to remove, etc. If I try to duplicate the steps again, it appears to replace the first one with the current. By the way, I am going to post this on Bill’s blog as well, in case you see it there first.

  13. Danny G Smith says

    I found the answer to the earlier post I had, the example file did not mention the file-list type, I see that in the source and it will do what I need. Thanks for a great product!

  14. Steve says

    I have been able to make this work in the backend with…
    __________________
    add_action( ‘init’ , ‘bullet_create_metaboxes’ );

    function create_metaboxes() {
    global $post;
    $prefix = ‘bt_';
    $meta_boxes = array();
    $meta_boxes[] = array(
    ‘id’ => ‘g-image’,
    ‘title’ => ‘Path to Image’,
    ‘pages’ => array(‘post’),
    ‘context’ => ‘side’,
    ‘priority’ => ‘low’,
    ‘show_names’ => true,
    ‘fields’ => array(
    array(
    ‘name’ => ‘ Image’,
    ‘desc’ => “Enter path”,
    ‘id’ => $prefix . ‘g_image’,
    ‘type’ => ‘text’
    ),
    ),
    );
    require_once(TEMPLATEPATH . ‘/lib/metabox/init.php’);
    }
    _________________

    But I can not get it to display on the front page.

    • Bill Erickson says

      What doesn’t work? Are you able to access it with get_post_meta($post->ID, ‘bt_g_image’, true); ?

      Also, your add_action references bullet_create_metaboxes, but the function is called create_metaboxes.

      • Steve says

        Nothing appears on the post page.
        *srry the action reference was a typo. it is the same in the functions.php though
        update–
        ____________
        add_action( ‘init’ , ‘create_metaboxes’ );

        function create_metaboxes() {
        global $post;
        $prefix = ‘bt_';
        $meta_boxes = array();
        $meta_boxes[] = array(
        ‘id’ => ‘gallery_image’,
        ‘title’ => ‘Path to Original Image’,
        ‘pages’ => array(‘post’),
        ‘context’ => ‘side’,
        ‘priority’ => ‘low’,
        ‘show_names’ => true,
        ‘fields’ => array(
        array(
        ‘name’ => ‘Gallery Image’,
        ‘desc’ => “Enter path”,
        ‘id’ => $prefix . ‘gallery_image’,
        ‘type’ => ‘text’
        ),
        ),
        );
        require_once(TEMPLATEPATH . ‘/lib/metabox/init.php’);
        }
        ____________
        on post page…
        get_post_meta($post->ID, ‘bt_gallery_image’, true);
        ____________
        Nothing shows on the post page. No matter what I try.

        • Bill Erickson says

          Try putting global $post; right before you do the get_post_meta.

          You an also try running the function the_meta(), which should output all post metadata. If it doesn’t show up there that means it’s not actually getting saved to the post.

          • Steve says

            I have used global $post;
            I just tried too.
            Nothing. Apparently there is another issue. Any ideas?

          • Steve says

            Hi Bill I found the error. I was trying to use this with a registered post type. I gt it to work on a regular post. What do I need to do to make this work with a ‘register_post_type’?

            I know I need to change the ‘pages’ field to the ‘register_post_type’ name, but something tells me I need to also change something in the init,php file. Is that correct?

  15. Bill Erickson says

    @Steve: If your post type is called ‘projects’, change the above to ‘pages’ => array(‘projects’)

    • Steve says

      That is exactly what I did and it did not work on the post made within that post type, but if I change it back to post it works on the normal post type outputs.

  16. Max says

    Hey Bill,

    thanks for this very helpfull class.

    I have a custom post-type ‘books’ for which I have a custom class ‘BookClass’.
    If I declare the meta in the theme functions.php everthing is fine.
    If I try to init the meta out of my class it is not showing up in the admin-panel of my custom post-type.
    Is it possible to call it out of a custom class?
    Is there something particular to keep an eye on?

    Sorry for this (maybe) stupid question… I just started to work with wordpress.

    Thanks in advance for a hint.
    Best regards Max

    • Bill Erickson says

      I’m sorry, but I don’t really understand the question. Could you rephrase it? What do you mean by “custom class” and “init the meta out of my class”?

      • Max says

        ok. Sorry my english is not very well. :-(

        I crated a php-class for my custom-post-type ( ), which is included in to my functions.php.

        So my thougt was, that the custom metaboxes belong to the class, so they should be created within the class, not in the functions.php.

        Hope this makes it clearer.

        Regards Max

        • Bill Erickson says

          I’m not familiar enough with PHP Classes to know the best way to do it. It sounds like a good idea to put it in there, but you’ll still need to have a metabox function that runs on init.

          add_action(‘init’, ‘be_create_metaboxes’);
          function be_create_metaboxes() {
          [however you pull the $metaboxes array from the class goes here]
          require_once(CHILD_DIR . ‘/lib/metabox/init.php’);

          }

          • Max says

            Thanks for the reply.

            That is what I have done.
            Seems that the “add_action( ‘admin_menu’, array(&$this, ‘add’) );” in “class cmb_Meta_Box” is not called if I try to create the MetaBox in my custom Class.

            The cunstructor of “class cmb_Meta_Box” is called.

            Very strange.

            Anyway, thanks a lot for your help.
            I think I can live with it in the functions.php.

    • Piet says

      You can add the following line at the bottom of the array:
      ‘std’ => ‘default-value’

  17. Joshua says

    Bill,

    I installed this on with my custom_functions.php file in thesis.

    At the top of the admin screen I get this error: Invalid argument supplied for foreach() in …/thesis_18/custom/lib/metabox/init.php on line 36

    I’ve added the example meta boxes in my functions file but they aren’t appearing in the custom post type I created (and I changed line 8 above to the custom post type).

    Thanks,
    Joshua

  18. Joshua says

    Bill,

    It looks as though this doesn’t work for WordPress 3.2. I just updated and it was working before, not after.

    Cheers,
    Joshua

    • Bill Erickson says

      It’s working for me on 3.2. If you are having issues try downloading the most recent version. Jared pushed out an update yesterday.

  19. Joshua says

    Bill,

    I’m trying to display the custom meta boxes in a custom post type. I’ve created a loop calling up the custom post types, it will display the_title() and the_content(), but I can’t get any custom meta values to show up. I’m using this code:
    $image = get_post_meta($post->ID,'rt_image',true);
    echo $image;

    but nothing appears. I figured it would be similar to any post meta value, but perhaps I’m over looking something obvious.

    Thanks!
    Joshua

    • Joshua says

      Nevermind, figured it out. Sorry to crowd your comments with silly requests! Moving to fast and overlooking the little things!

  20. Piet says

    Hi Bill,
    Thanks for the great code, this is really helpful!
    One thing I cannot seem to get working is saving the values of checkboxes and/or radio buttons. They show in the backend, but when I tick a box or select a radio button and click Update, it comes back empty. Am I forgetting something?

      • Bill Erickson says

        I just tested it and it works fine for me. Here’s what I used:

        array(
        ‘name’ => ‘Sample Checkbox’,
        ‘desc’ => ”,
        ‘id’ => $prefix.’checkbox’,
        ‘type’ => ‘checkbox’
        )

        • Piet says

          Thanks for your reply Bill, it was my own silly mistake, got it working too now and it does a tremendous job! Thanks!

  21. Piet says

    I have one last question. Before I was using your class, I used another, similar metabox class by deluxeblogtips (http://senl.in/q2zpAV). That was all working fine until WP 3.1.4. Upon the release of WP 3.2 the script broke the wysiwyg editor, so I needed to find an alternative. I am therefore very happy that I found your script (recommended by a friend).

    One of the features the other script had though was the ability to upload multiple images. I have seen that your script also has an image upload field, but I am wondering whether that also works for multiple images and whether it will be possible to sort those images after upload.

    If it is possible, then that’s great of course. If not, then it might be an idea to try to implement that functionality in your script too?

    • Bill Erickson says

      I believe the image upload type only allows one image, which is the most common use case. If you want multiple images uploaded I recommend turning on the editor and using the Media Uploader, or just adding to the media uploader to the post type. That way you can use the gallery feature.

  22. Piet says

    Hi again Bill, I seem to be running into the same problem as with the other script: the wysiwyg-editor is not showing up, screenshot: http://senl.in/oDmcUd

    The code I used is exactly according the example-functions:
    array(
    ‘name’ => ‘Review Summary’,
    ‘desc’ => ”,
    ‘id’ => $prefix . ‘summary’,
    ‘type’ => ‘wysiwyg’,
    ‘std’ => ‘some default text’
    ),

    Has this happened before to anyone? I am using a TwentyTen child theme and have upgraded to WP 3.2

  23. Tom says

    Hi Bill. I’m very inexperienced with WordPress and PHP but your metabox code, and this article, has made the creation/implementation of Custom Meta Boxes super easy, so thank you! I’ve implemented CMBs for a custom-post-type but have since been mulling over other ways to use them and wondered if it’s possible to show CMBs on a specific page only? I hoped that ‘pages’ => array(‘page_name’) would work but it does not.

    • Bill Erickson says

      Unfortunately no, you can’t display it on a specific page. But you could use CSS to hide the metabox on all pages except the one you want it on. It’s beyond the scope of this post, so search around for Admin CSS.

        • Tom says

          Just thought I would follow this up in case any one else is interested. Kevin Learyhas a useful article that basically walks you through exactly what’s needed.

          • Bill Erickson says

            @Alex I’ve added page-specific code to the metabox script for a few client projects and do want to add it to the core. But I have another feature that’s more important and will most likely result in a complete rewrite, which is why I’ve held off.

            I want to rebuild it so you can easily add new field types without editing the core (you add the code either to your theme or plugin). It would be done with a filter or hook, and then all the default field types will also be added through that means.

            Once I have this built it should be pretty easy to add page-specific filtering of the metabox.

  24. says

    Thanks for the great code Bill, just a small question left. I managed to create one box with multiple fields in them. Is it possible to create multiple boxes (for example one on the left and one right) and how? Thanks again!

    • Bill Erickson says

      Yes, you can create multiple boxes, just duplicate the code you used to create the first box and change its title and id. But each one will be a full metabox – you won’t be able to float them next to each other (except with additional CSS).

  25. says

    Wonderful script.

    I have had some problems with the file-upload function, specifically using a custom post type where I have disabled the default wordpress wysiwyg box. In this instance, the thickbox with the file upload dialogue opens WAY off page – lower-left corner, about 300px below the footer. It works fine in another CPT where I have enabled the default wysiwyg.

    I’m wondering if this is a known bug, and if there is a way to fix it. I am going to enable the default WYSIWYG for the CPT for the time being, but it would be ideal if I could still use file upload without using the default WYSIWYG.

    Thank you!

  26. says

    Bill,

    Would it be possible to use a metabox to add a URL and then when the page is called via a link within the site, page launches a new window and displays the URL in the metabox? Almost like a 301 redirect, but in a new window.

    Alan Smith
    Media317

    • Bill Erickson says

      Yes, the metabox could collect the URL, but I don’t know what technique you’d use to automatically open a page in a new window without it being blocked by most browsers.

  27. says

    Hi Bill
    Thanks a lot for you’re tutorial. When you use Genesis, I wonder if there is a way to change the priority of Genesis Meta box to put your own meta meta box above them

    • Bill Erickson says

      If you change the priority of your metabox to high (from low in the example below) it should show up above the Genesis metaboxes.

      You could remove the function that adds the metaboxes and duplicate it in your child theme using the “low” priority, this isn’t future compatible. If Genesis comes out with new/updated/removed metaboxes, your code won’t reflect that.

  28. says

    Hi Bill, awesome script! One problem I’m running into though. The “Add Image” or “Add Gallery” features in the WYSIWYG editor are not working correctly. I can upload and do all that jazz, but as soon as I try to “insert into post” I get a “Too much recursion” error in the console in Firebug and the image editor lightbox goes blank. It looks like there is something wacky going on in the jquery.cmbScripts.js file on line 81 “window.original_send_to_editor(html);” I’m having some trouble getting this to work. Any ideas?

  29. Scott says

    Excellent script and nice to you responding to issues, however preliminary or elaborate, well after its release.
    Kudos.

  30. says

    Thanks for the great script Bill. I can’t get shortcodes to work in WYSIWYG, they do if I use in WP text editor but not in additional editors. Is that something I do wrong or it’s not really possible ?

    • Bill Erickson says

      Shortcodes are only executed on the post editor because there’s a filter that runs on it. For anything else (like your custom fields) you’ll need to wrap it in do_shortcode( ). Let’s say you created a custom field called “be_extra_content” and wanted shortcodes to be executed on it.


      global $post;
      // Get the field
      $extra = get_post_meta( $post->ID, 'be_extra_content', true );
      // Filter it for shortcodes
      $extra = do_shortcode( $extra );
      // Show the content
      echo $extra;

  31. Steve says

    Love the library! Quick question for you:

    I need to store loads of events as custom post types, planning on using the date picker. Any way within your guys’ code to format the date to timestamp (i.e. 20110916) rather than 09/16/2011? How would you approach this using your custom metaboxes lib?

    • Bill Erickson says

      I use the metabox code for event post types all the time. Use the ‘text_date_timestamp’ field type because it will store it as a UNIX timestamp. Makes event queries easy

  32. mampranx says

    How to add default radio checked?

    array(
    ‘name’ => ‘Test Radio inline’,
    ‘desc’ => ‘field description (optional)’,
    ‘id’ => $prefix . ‘test_radio’,
    ‘type’ => ‘radio_inline’,
    ‘std’ => ‘ ??? ‘
    ‘options’ => array(
    array(‘name’ => ‘Option One’, ‘value’ => ‘standard’),
    array(‘name’ => ‘Option Two’, ‘value’ => ‘custom’),
    array(‘name’ => ‘Option Three’, ‘value’ => ‘none’)
    )
    ),

  33. Alex Barber says

    Here’s an out there implementation question. I’m trying to use a bit of custom code that someone wrote to make a call to Google Maps API based on a custom address field. It parses returned XML to a lat/long pair and writes it to appropriate custom fields. This code uses “publish_post” while your code uses “save_post” to update custom field values and the lat/long fields never update with the returned values. Any thoughts on how I can get the two to peacefully co-exist?

    • Bill Erickson says

      You’ll probably need to modify one or the other. As shown here, publish_post runs before save_post. Maybe you could try changing the custom code to use ‘save_post’ and a later priority (like 15).

      • Alex Barber says

        That seems to have worked. I was trying save_post and publish_post yesterday, but I wasn’t playing with priorities. I set the Google code to run with save_post with a priority of 15 and it populates the fields now.

  34. says

    Bill,

    I have the following in my functions.php

    [removed by Bill]

    but the metabox does not display on the custom post type’s creation page. I’ve tried adding global $post before $prefix and that did nothing. I’m at a loss. Any thoughts? Thanks.

    I’m testing this on 3.3 alpha in a Genesis child theme.

    • Bill Erickson says

      The code that I had posted here on this page was out of date. The metabox code now uses a filter. See the updated code above, or refer to the example-functions.php file in github.

  35. says

    Bill, thanks again for the great framework (I use it in almost every project). Is there any way to add text fields (or any other) dynamically inside page editor just like widgets? For example I need to create flexible box so user can add as many items as they want ( so the number of inputs is different for each page ). thx

    • Bill Erickson says

      It sounds like the easiest method would be to use the Custom Fields functionality in WordPress. It lets you add as many fields as you want. When creating a metabox you have to define them all upfront in code – the client can’t add new ones on specific pages.

  36. says

    Hey Bill,
    Is there anyway, I can have different types of meta boxes for each page.
    Lets say I have the following pages: Home, Contact, About
    Can i have different meta boxes for Home and different meta boxes for Contact and About, even though the post type for all three is array(‘page’) ?

    Thanks

  37. says

    Another quick question: When using field type file, is there currently any way to retrieve the attachment ID rather than the full URL to the inserted image? I’d like to use image presets via add_image_size. Thanks!

  38. says

    I’m learning a ton. When I start putting this to use in client themes I’m sure I”ll run into hiccups. Do you recommend a place to go to for help? Is something like this beyond the support offered at StudioPress?

    Thanks for the tut!
    Cathy

  39. logesh says

    Hi Eric
    Thanks for this useful tutorial. Your code worked great for my genesis project .But now i am using nova theme from Elegant themes.I followed the same steps as I did for genesis but I am getting this error .Please help me out.Thanks in advance.

    Fatal error: Call to undefined function apply_filters() in /home/ravidrin/public_html/madmac/wp-content/themes/Nova/lib/metabox/init.php on line 36

    Warning: Cannot modify header information – headers already sent by (output started at http://ravidreams.in/madmac/wp-content/themes/Nova/lib/metabox/init.php:3) in /home/ravidrin/public_html/madmac/wp-includes/pluggable.php on line 934