5

Having trouble finding info on this. When working with lots of metadata/custom fields, I would really prefer to simplify getting the meta data inside of templates instead of using get_post_meta and instead keep the setting up of that data in the back-end where it belongs to keep my templates clean and easier to work with.

Is there a way to do this?

<p><?php echo $something->meta_field_name ?></p>

This would be similar to how you can do things like $post->ID or $post->post_parent that are in WordPress core, except it would be for custom post types and custom fields. If this is not possible, I guess the next question would be, why?


Edit: Since I've seen this mentioned several times in responses, when writing PHP like this you have to escape the output, which I do. I left out the escaping for brevity, but for anyone new to it, here's how I would typically write this (and thanks to @fuxia for the solution to my original question).

Escaping (with the solution) for WordPress:

<p id="text-<?php echo esc_attr($post->post_name) ?>"><?php echo esc_html($post->meta_key_name) ?></p>

And if you're outputting to a class:

<p class="text-<?php echo sanitize_html_class($post->post_title) ?>">Clean Class</p>

I typically wouldn't use post_title but using it as an example as sanitize_html_class will remove white space and only keep alphanumeric characters, underscores and dashes.

If outputting things like JSON-LD, you can combine escaping:

"@id": "<?php echo esc_js(esc_url($link)) ?>#<?php echo esc_js($post->post_name) ?>",
"name": "<?php echo esc_js($post->post_title) ?>"
4
  • I believe the reason this isn't possible is because post_meta is in a separate table, whereas the examples you cited are part of the posts table, so when you retrieve a post, data like id and post_parent or guid are returned in that row, but when retrieving post_meta you're using the ID to run a secondary DB call to a different table. I guess it could be done by writing a custom function, but I really don't see why that would be necessary. Commented Oct 31, 2021 at 19:49
  • note that there is no escaping in your example, and there are no opportunities for filters to run. This also won't work if there is more than one meta with that key ( meta keys are not unique ). There may be plugin compatibility issues with this. Custom post types are just post types, the same as the page or post type etc, they're stored the same way and handled the same way ( except that posts have rewrite rules and templates for date archives )
    – Tom J Nowell
    Commented Oct 31, 2021 at 20:09
  • Yeah, I was trying to brief. `<p><?php echo esc_html($something->meta_field_name) ?></p>
    – liquidRock
    Commented Oct 31, 2021 at 20:32
  • I have updated my post with the solution and showing how I escape output, for those who are new to it.
    – liquidRock
    Commented Nov 1, 2021 at 21:12

1 Answer 1

9

Getting meta data from a WP_Post object is already possible. Just write:

echo $post->your_meta_key;

This will call get_post_meta( $this->ID, $your_meta_key, true ) behind the scenes.

See the documentation and the source code for WP_Post.

This works also with instances of WP_User, but not with WP_Comment as far as I know.

Don't forget to escape the output!

5
  • 2
    I didn't realize that. This will come in handy.
    – Pat J
    Commented Oct 31, 2021 at 20:25
  • 2
    You've got to be kidding me... -_- I don't believe I've seen this anywhere. Feel like stabbing my computer right now. Well, at least it works. Guess I'll be spending the next 2 days rewriting my templates. Thank you!
    – liquidRock
    Commented Oct 31, 2021 at 20:35
  • 1
    Completely forgot about __get, nice to know that WordPress uses magic methods, now I wonder where else did they use them. WordPress has some hidden gems that its a shame that they don't document them better. Commented Nov 1, 2021 at 9:35
  • 1
    @Buttered_Toast WP_User is another example. I have updated my answer.
    – fuxia
    Commented Nov 1, 2021 at 10:08
  • virtual -1 for the property way. Some day in 2030 there will be a new field in the post object and it will collide with your meta name. Don't use magic methods unless you must because it makes the code less readable. Commented Nov 2, 2021 at 4:14

Your Answer

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

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