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){
    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);
  • 2
    What you are doing should work. What "value" has not been passed? – s_ha_dum Nov 8 '13 at 15:35

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.

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

function getqtlangcustomfieldvalue($metadata, $object_id, $meta_key, $single) {
    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.

  • 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() – Zlatev May 19 at 9:55

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(

    return $single ? '' : [];

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

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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