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);

protected by Pieter Goosen Nov 14 '15 at 13:08

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

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