Steve Taylor photo

WordPress custom fields reloaded

PLEASE NOTE: This code has now evolved into the Developer’s Custom Fields plugin.

My post on controlling your own WordPress custom fields is by far and away the most popular post on this site. Maybe I should monetize it or something?

Well, for a start, as a good friend once said, the word “monetize” should be take outside and shot. Besides, building WordPress sites does very well for me.

A better idea: improve the code!

This revamp is pretty major. I’ve incorporated a lot of lessons learned, and added many new features. It’s verging on plugin territory, but there’s already good plugins for this kind of thing. As ever, my target is the intermediate WP developer who wants to fold some code into their custom theme’s functions.php file, and be free to customize and tailor the code to fit their needs. If you’re not comfortable with PHP and with building WordPress custom themes, check out a plugin like Custom Field Template or Magic Fields. It’ll probably save you some pain :)

On the other hand, if you kind of know what you’re doing, but can’t work something out, or find a bug, I’ll be delighted to help.

So, what’s new?

  • Full support for custom post types
  • The ability to create different meta boxes for your fields
  • Field types galore!
    • Plain text
    • Textarea (both with the option for allowed HTML tags and wpautop formatting)
    • Simple Textile-style formatting
    • TinyMCE visual editor
    • Drop-down or multiple select boxes (including optgroup support)
    • Radio buttons
    • Single or multiple checkboxes
  • Dynamic population of options for selects, radios and multiple checkboxes
  • Better checks to screen for autosave and post revision save actions
  • Variables for flexible styling
  • Numerous cool code improvements


  • PHP 5 (WP itself is dropping support for PHP 4 very soon)
  • WordPress 3+ (I think—it might work with earlier versions, but you’re on your own)


  1. Download this ZIP file
  2. Unzip it and upload the PHP file into your custom theme’s folder
  3. Use something like require_once( 'functions_admin_custom-fields.php' ); in your functions.php to include it
  4. Set up the $boxes and $customFields arrays as necessary; some SEO-related defaults are included
  5. For people who have already been using my original custom fields code, change the $prefix variable at the top to _mcf_ (or whatever you’ve used—see note below)
  6. Test thoroughly before deploying on a live site!

A few words of explanation

The code is well commented, and documentation for the meta boxes and field types is given inline. However, a few things to point out:

  • The prefix that’s set at the start is just my initials :)  I use it in all my code, not for ego reasons, but because it makes my custom theme code much more portable for myself. Feel free to change it to something else if you like, but make sure you change it before you start using the code, and don’t change it from then on. You won’t really lose data by changing the prefix after a while, it’ll still be in the postmeta table; you’ll just lose access to it through this interface, and things will get confusing. As mentioned above, if you’re “upgrading” from the older version of this code, well, I’ve not really designed this with anything as neat as “upgrading” in mind. However, as long as you change the prefix to the one that you’ve been using, whether it’s _mcf_ (“my custom fields”) as in my example, or something else. I’ve not tested this, but in theory this code should then pick up all your meta fields. Let me know if you hit any snags on this.
  • Multiple checkboxes, like multiple select boxes, are stored as one entry in the postmeta table. An array is created of the values that are checked, and update_post_meta() kindly serializes the array for storage. Likewise, get_post_meta() will kindly unserialize such values.
  • A handy getter method is provided, so you don’t have to remember to use the prefix when getting meta values. Just use slt_customFields->getFieldValue( 'key' )

Room for improvement?

Of course! I’ll try and include any fixes and additions I come up with—please let me know of any of yours. Some notes:

  • No file upload :(  Yet…
  • Because I started with all the custom fields in one meta box, then added boxes, the two are set up separately, with fields being assigned to a box. One tutorial that also attacks this issue has the fields has entries in the box arrays. I can see a few pros and cons either way, but nothin major. Do let me know if you spot any major pros or cons of either approach.
  • The code used to include a TinyMCE editor is almost identical with that used in my first attempt. The client found that on occasions, the custom editor seemed to be writing its contents into the main content editor! Obviously not good. I managed to repeat it once or twice, but never consistently; I reverted them to a Textile-type field to be safe. I’ve given the above code a good test, and the WYSIWYG options seems to work OK, but do let me know if you come across any issues, or see any improvements that could be made.
  • I noticed that when I changed the name of a meta box after I’d used it a few times, it didn’t appear properly. Anyone else find this? An obvious workaround is to pick box names carefully and stick with ’em.
  • Multiple checkboxes and multiple selects are kind of similar in some ways. I thought about trying to merge their code in some way, but I think the way it’s done now is most economical. Or is it?
  • I’ve set up the processing of text—stripping tags, adding paragraphs, etc.—in a way that’s hopefully intuitive and flexible. Let me know if you spot any glitches in the flow of this stuff.
  • Obviously the Textile function could be expanded…

Anyway, hope you have fun with the code.


  • 30/11/10: Change how dynamic options are handled, introducing optionsType and optionsQuery parameters, and removing posts as a field type. Dynamic data can now be passed through to checkboxes and radio buttons instead of being limited to selects.


  1. Folks, I’m realizing more as I keeping adding tweaks, I need to spend a little more time on this and separate the definition of the boxes and fields from the main code file. Then “upgrading” will at least be feasible. Feel free to play away with the code as it is and let me know how you get on, but watch this space for something a bit more portable. It should be easy to switch from the current code when it comes.

  2. Greg avatar Greg

    Thanks for posting this, I’m excited to add a bit more functionality to the custom fields area.

    The plugins I have tried seem a bit like over kill, or just not as discreet as this approach. (personal preference I guess)

  3. Thanks Greg, let me know of your experiences! To be honest I think I’ve released a little early… I can see so many things that would be good to add on, as well as abstracting things so the field definitions are separate. For now, consider this code to be public beta :)

  4. Hi Steve —

    Thanks very much for this code. I also found the custom field plugins unwieldy and not quite what I needed. Your solution was actually easier for me to implement.

    I would be great to be able to target this field for file uploads. I’ll look at the site you linked and let you know what I think when I have time.

    Another feature that would be great is an html view tab. I realize that leaving the default custom fields meta box visible sort of serves this purpose, but then only changes to that field and not the wysiwyg version are saved on update. That is too confusing for the end user who needs the wysiwyg. With the html tab, it just makes the raw code view available to those who know how to use it.

  5. Hi Gretchen, file uploads should be coming soon. I’m so busy everything is dictated by client requirements, but a client needs a file upload before 2011, so hang on :)

    I agree that the HTML tab view should be there – obviously it’s not by default. I’ll see if I can work out how to activate it. Anyone know?

  6. Was wondering if you could elaborate a bit on the options for fields. Guess what I’m really looking for is just a couple little examples of using a select field for optionsQuery, like, how it would be entered in. Then, also how to fill a default value into a static field. The documentation shows “e.g. array( “label1” => “value1”, “label2” => “value2″ )” but I don’t know what lable1 and value1 are meant to represent.

    Thanks a ton…this whole thing is absolutely amazing and answers soo many questions I’ve been having.

  7. Hi Joe, regarding default values (for any type of field), that’s an essential feature I hadn’t realized was missing. Feel free to code your own for now until a get a new version done.

    As for populating the array, just install the code on a test site and try it out! It’ll quickly become clear where the label and value bits of the array are used. Hint:

Comments are closed.