Craig Simpson

Web developer from Moray, Scotland

How to render ACF Wysiwyg fields correctly

20th April 2017

6 Comments

Advanced Custom Fields (ACF) allows you to add a WYSIWYG field, like the WordPress visual editor, as a custom field on your pages or posts. When you’re editing this field in the backend, you can apply formatting and styles as you normally would in the post editor.

When you come to output the field, however, you may find that if you’re using get_post_meta to look it up, any special formatting you’ve applied may be gone.

To get around this issue, I like to create a new filter called meta_content which we can apply to our custom post field. The idea here is that we utilize all of the functionality normally applied with the the_content filter to present our Wysiwyg field properly. Adding the following code to your functions file or plugin will make this filter available for use in your template files.

1/**
2 * Create new 'meta_content` filter.
3 *
4 * Recreate the default filters applied to `the_content`,
5 * so content retrieved using `get_post_meta` can be
6 * formatted in the same way.
7 */
8add_filter( 'meta_content', 'wptexturize' );
9add_filter( 'meta_content', 'convert_smilies' );
10add_filter( 'meta_content', 'convert_chars' );
11add_filter( 'meta_content', 'wpautop' );
12add_filter( 'meta_content', 'shortcode_unautop' );
13add_filter( 'meta_content', 'prepend_attachment' );

From there on, you can look up your custom field as normal, using:

$field = get_post_meta( get_the_ID(), 'field_name', true );

And then when you want to output it, simply apply our filter, like so:

echo apply_filters( 'meta_content', wp_kses_post( $field ) );

This means we can use the same filter throughout our theme or plugin files, and can also add or remove the filters we don’t need. For example, if you normally disable emoji support (as I do on most new sites), then you can simply remove the call to add_filter( 'meta_content', 'convert_smilies' );.

** Updated on July 6th 2017 to correctly escape our field content before output using wp_kses_post. Thanks to Mark Wilkinson for suggesting this edit.

6 comments

  1. Hi Craig,

    I do something similar here, however I notice you are not escaping or sanitising the output on the frontend.

    I think it would better for the output to be like this:

    1. Craig Simpson says:

      That’s a great point, Mark. I’ve updated my original post with your suggested edit. Thanks for stopping by 🙂

  2. Tim Jensen says:

    Hey Craig, first of all this is a really great approach! Just one suggestion…it might be nice to add a few extra filters so that shortcodes and embeds get processed like they do with 'the_content' filter:

    $wp_embed = new \WP_Embed();

    add_filter( 'meta_content', 'wptexturize' );
    add_filter( 'meta_content', 'convert_smilies', 20 );
    add_filter( 'meta_content', 'convert_chars' );
    add_filter( 'meta_content', 'wpautop' );
    add_filter( 'meta_content', 'shortcode_unautop' );
    add_filter( 'meta_content', 'prepend_attachment' );
    add_filter( 'meta_content', 'do_shortcode', 11 );
    add_filter( 'meta_content', [ $wp_embed, 'run_shortcode' ], 8 );
    add_filter( 'meta_content', [ $wp_embed, 'autoembed' ], 8 );

    1. Dan says:

      Tim (or Craig) – I’m in the process of adding this functionality to my site, and I’m curious what the backslash in your “$wp_embed = new \WP_Embed();” line does? Is that just a formatting byproduct of adding a comment here, or is that necessary for some reason?

      1. Craig Simpson says:

        Hi Dan, the backslash in PHP is used in namespaces. It’s the start symbol to indicate a namespace and also serves as a separator between sub-namespace names.

        In this context, Tim has used `new \WP_Embed()` to create a new instance of WP_Embed from the global (root) namespace, rather than potentially a different WP_Embed class that exists within his project.

        If you don’t use namespaces in your project then you can keep the backslash, or remove it, with no ill effects.

        Some more info on namespaces if you’re interested, at https://www.php.net/manual/en/language.namespaces.basics.php

Leave a Reply

Your email address will not be published. Required fields are marked *