9

How to hook a filter to catch get_post_meta when alternate a custom field output?

I have fill a custom field(meta data) in a post, just like this:

<!--:de-->Nominale spanning<!--:--><!--:zh/cn-->额定电压<!--:--><!--:en-->Arrester Accessories<!--:-->

I need to get this output translated,so I wondering how to hook into "get_post_meta" before the meta data output.

Here is what I've tried for a few days, but no luck.

function getqtlangcustomfieldvalue($metadata, $object_id, $meta_key, $single){
    $fieldtitle="fields_titles";
    if($meta_key==$fieldtitle&& isset($meta_key)){
         //here is the catch, but no value has been passed
    }
}
//Specify 4 arguments for this filter in the last parameter.
add_filter('get_post_metadata', 'getqtlangcustomfieldvalue', 10, 4);
1
  • 2
    What you are doing should work. What "value" has not been passed?
    – s_ha_dum
    Nov 8, 2013 at 15:35

3 Answers 3

17

After a lot of messing around with this, I think I found a fairly good solution here. I realize this is over a year after you asked but this was bothering me and I couldn't find a good solution until now.

The problem is that the get_post_metadata function doesn't allow you to access the current value. This means you aren't able to transform the value, just replace it. I needed to append content to a meta field and where it was output did not allow filters of any kind.

Here's my solution, altered to fit what this question asks:

function getqtlangcustomfieldvalue($metadata, $object_id, $meta_key, $single){

    // Here is the catch, add additional controls if needed (post_type, etc)
    $meta_needed = 'fields_titles';
    if ( isset( $meta_key ) && $meta_needed == $meta_key ){
        remove_filter( 'get_post_metadata', 'getqtlangcustomfieldvalue', 100 );
        $current_meta = get_post_meta( $object_id, $meta_needed, TRUE );
        add_filter('get_post_metadata', 'getqtlangcustomfieldvalue', 100, 4);

        // Do what you need to with the meta value - translate, append, etc
        // $current_meta = qtlangcustomfieldvalue_translate( $current_meta );
        // $current_meta .= ' Appended text';
        return $current_meta;
    }

    // Return original if the check does not pass
    return $metadata;

}

add_filter( 'get_post_metadata', 'getqtlangcustomfieldvalue', 100, 4 );

This will keep any other get_post_metadata filters intact and allow modification of the original value.

1
  • If you're getting a serialized array from post meta, maybe you need to return the value inside a new array. Example: return array( $metadata ); Dec 22, 2022 at 22:18
7

Just had the same problem and, using your code above, here is how I solved it:

function getqtlangcustomfieldvalue($metadata, $object_id, $meta_key, $single) {
    $fieldtitle="fields_titles";
    if($meta_key==$fieldtitle&& isset($meta_key)) {
        //use $wpdb to get the value
        global $wpdb;
        $value = $wpdb->get_var( "SELECT meta_value FROM $wpdb->postmeta WHERE post_id = $object_id AND  meta_key = '".$meta_key."'" );

        //do whatever with $value

        return $value;
    }
}
add_filter('get_post_metadata', 'getqtlangcustomfieldvalue', 10, 4);

I tried using apply_filters, get_metadata, get_post_meta directly within the function but they wouldn't allow me to manipulate the resulting output, so I resorted to using $wpdb.

3
  • 1
    Beware, this will prevent the filtered meta from being cached in object cache. @joshcanhelp's solution won't suffer from that since it still call get_post_meta()
    – Z. Zlatev
    May 19, 2018 at 9:55
  • This will DDOS your database server.
    – svandragt
    Jan 29, 2019 at 11:31
  • Correct on caching. get_post_meta is better to use, but at the time back in 2014, it wouldn't run in the function. But crash a db server - I don't think so. The get_var query is equivalent to get_post_meta and is a simple query. Even if it were run hundreds of times on a page, it would not crash a server. It's been running on production since 2014 with no issues.
    – forlogos
    Jan 30, 2019 at 12:32
0

Here's my solution for filtering post meta. This then calls a custom function to perform any required data manipulation.

public function filter_post_meta($metadata = null, $object_id, $meta_key, $single)
{
    $meta_cache = wp_cache_get($object_id, 'post_meta');

    if ( !$meta_cache ) {
        $meta_cache = update_meta_cache( 'post', array( $object_id ) );
        $meta_cache = $meta_cache[$object_id];
    }

    if ( ! $meta_key ) {
        foreach ($meta_cache as $key => $val) {
            foreach ($val as $k => $v) {
                $meta_cache[$key][$k] = yourCustomFunction($v);
            }
        }

        return $meta_cache;
    }

    if ( isset($meta_cache[$meta_key]) ) {
        if ( $single ) {
            $value = maybe_unserialize( $meta_cache[$meta_key][0] );

            return yourCustomFunction($value);
        } else {
            return array_map(
                'maybe_unserialize',
                array_map(
                    'yourCustomFunction',
                    $meta_cache[$meta_key]
                )
            );
        }
    }

    return $single ? '' : [];
}

add_filter('get_post_metadata', 'filter_post_meta', 100, 4);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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