So, like the title says, I'd like a single function to get an aggregate list of all custom fields, site-wide (all posts, pages, CPT's). Normally, I do this with a couple SQL statements and juggle the results, but I was wondering if anyone's come up with a more core-oriented way of doing this. Mostly, though, I wanted something available online and easy-to-find for someone else searching for this.

Here's the SQL I normally use:

SELECT DISTINCT `meta_key` FROM `prefix_postmeta` WHERE `meta_key` NOT LIKE "\_%"

Here's a function to pull a single page or post's custom fields:

$custom_fields = get_post_custom($post->ID);

foreach ( $custom_fields as $field_key => $field_values ) {
    if ( ! isset( $field_values[0] ) ) continue;
    if ( in_array( $field_key, array( "_edit_lock", "_edit_last" ) ) ) continue;
    echo $field_key . '=>' . $field_values[0];

So basically, I'd like a one-off function that I can stick in functions.php and call up when I need an up-to-date cut/paste list of all my custom fields for a plugin that makes you list them all out by hand - Broken Link Checker, for example.

  • Afaik, there isn't something like that. Not for this, or any other table. But I guess, you could write some query, that only pulls the ID incl. the meta you're after. – kaiser Jul 10 '12 at 7:04

The function below will store a distinct list of all custom fields for the list of posts/pages/custom posts that is passed to it in the keys of the array $customfields. The array values are the number of posts with the corresponding field. In the example, custom fields added by plugins are excluded ($value[0] != '_';) but these could easily be added back in.

function all_custom_fields($allposts) {
    foreach ( $allposts as $post ) : setup_postdata($post);
        $post_id = $post->ID;
        $fields = get_post_custom_keys($post_id);    // all keys for post as values of array
        if ($fields) {
            foreach ($fields as $key => $value) {
                if ($value[0] != '_') {              // exclude where added by plugin
                    $customfields[$value] = isset($customfields[$value]) ? $customfields[$value] + 1 : 1;
    endforeach; wp_reset_postdata();
    return $customfields;

// example - all post types, whether published or not
$args = array(
    'post_status' => array('publish','draft','pending','future'),
    'post_type' => 'any',
    'posts_per_page' => -1,
$allposts = get_posts($args);
$customfields = all_custom_fields($allposts);

Not the answer you're looking for? Browse other questions tagged or ask your own question.