Get custom fields for WordPress post

This post is more than 12 years old.

WordPress lets you store custom fields on your posts (and pages, and custom post types that allow it). However, it gives them to you in a rather inconvenient manner, with your values mixed in with its own special fields and any plugin’s special fields, and with values in an array. Here’s how to easily deal with that.

If you want to allow for a bunch of free-form custom fields, and simply iterate over them to show them on a web page, you probably don’t want to deal with the cruft of WordPress’ and plugins’ special fields, or the fact that the get_post_custom() function returns field values in an array. Yes, even when there’s only one value for your custom field, it comes back as an array.

The function below uses a few nifty array manipulation functions in PHP to help sort all of that out.

  • array_map() runs a function over every element in an array
  • implode() concatenates elements of an array into a string
  • array_keys() gets the keys from an associative array as values in an array
  • preg_grep() searches the values of an array by regular expression match
  • array_flip() exchanges the keys and values in an array
  • array_intersect_key() returns only the elements from the first array that have keys in the second array

The implode() function is an oddball: you generally give it two arguments, the glue to join the elements and the array to implode. However, it can also accept just one argument, the array, which makes it useful here for calling from array_map() which only passes one argument to the callback function.

Putting it all together, here’s a function that gets custom fields for a post, ignoring any special fields, and gives you a simple key=>value associative array.

/**
* get custom fields for post, ignoring special fields (which start with '_')
* @param int $post_id optional, will assume current post
* @return array simple key=>value associative array
*/
function getPostCustom($post_id = 0) {
    // get all custom field values for post
    $custom = get_post_custom($post_id);

    // values are arrays each with a single element;
    // reduce value arrays to strings
    $custom = array_map('implode', $custom);

    // we only want regular custom fields, not special fields
    // e.g. fields used by plugins to store other data;
    // get list of fields with keys that don't start with '_'
    $matches = preg_grep('/^[^_]/', array_keys($custom));

    // flip the array to get the field names as keys again
    $matches = array_flip($matches);

    // return only the elements with matching field names
    return array_intersect_key($custom, $matches);
}

With a few handy functions, job is done in just a few lines of code.