Make WordPress Core

Opened 14 years ago

Last modified 20 months ago

#14017 assigned enhancement

New template "tag": get_custom_field()

Reported by: filosofo's profile filosofo Owned by: obenland's profile obenland
Milestone: Future Release Priority: normal
Severity: normal Version: 3.0
Component: Posts, Post Types Keywords: has-patch needs-unit-tests dev-feedback
Focuses: template Cc:

Description

It would be helpful to have a way to retrieve a custom field value that is somewhat agnostic of current context.

Current way to do this

In the header (i.e., before the Loop), one has to access the currently-queried object to get a custom value, with something like this:

$value = get_post_meta($GLOBALS['wp_query']->get_queried_object_id(), 'field', true);

In the Loop:
$value = get_post_meta(get_the_ID(), 'field', true);

And, lots of tutorials out there tell people to do things like the following, with varying degrees of success (depending on variable scope):

$value = get_post_meta($id, 'field', true);

or

$value = get_post_meta($post->ID, 'field', true);

My proposed function (or "template tag")

mixed get_custom_field ( string $fieldname [, int $post_id ] )

$value = get_custom_field('field');

It picks the current object like so:

Passed post object ID?
    /       \
   yes      no 
    |        |
   use it    |
             |
          within Loop?
            /       \
          yes        no
           |          |
        use current   |
         Loop ID      |
                      |
                    currently queried
                    object is singular?
                    /           \
                   yes           no
                    |             | 
                use its ID      ID = 0

Attachments (1)

get_custom_value.14017.diff (1.0 KB) - added by filosofo 14 years ago.

Download all attachments as: .zip

Change History (17)

#1 @nacin
13 years ago

  • Keywords commit added
  • Milestone changed from Awaiting Triage to 3.1

This makes a lot of sense. A friend was asking how to do this earlier, and I went through the same thought process as above when explaining it. +1

#2 @filosofo
13 years ago

Patch is still a thing of beauty.

#3 @westi
13 years ago

  • Keywords commit removed

Not convinced about the naming of this.

It really irks me that we call post meta by two different names and promoting that more here is not good IMHO.

Can we not just extend get_post_meta() to have this behaviour if passed a 0 id?

#4 @filosofo
13 years ago

I don't really care about the name, so please suggest one. However, they're called "Custom Fields" on the post edit page, so it seems like the reasonable name to me. The name of the db table the actual data is stored in is irrelevant to the person using the API, right?

I think changing get_post_meta to accept 0 as an argument like that is going to have serious backwards-compatibility issues, because get_post_meta should fail when given an invalid ID. And then they still have to add "true" to make sure they get a string.

My general idea is to make the lives of template designers easier.

#5 follow-up: @nacin
13 years ago

I don't care what we call it, but it's a very nifty function.

get_post_meta_field()?

#6 in reply to: ↑ 5 @markmcwilliams
13 years ago

Replying to nacin:

I don't care what we call it, but it's a very nifty function.

Got to agree with you there! :)

#7 @westi
13 years ago

  • Keywords 3.2-early added
  • Milestone changed from 3.1 to Future Release

This is possibly a nifty idea.

But it is past the time for introducing new apis in 3.1

We should consider this for 3.2 though

#8 follow-up: @scribu
13 years ago

How about we make a WP_Post class, with a custom_field() method:

echo $post->custom_field( 'key' );

Of course, it could be extended with other methods too.

#9 in reply to: ↑ 8 @mikeschinkel
13 years ago

  • Cc mikeschinkel@… added

Replying to scribu:

How about we make a WP_Post class, with a custom_field() method:

echo $post->custom_field( 'key' );

Of course, it could be extended with other methods too.

+1

#10 @jaredatch
12 years ago

  • Cc jared@… added
  • Keywords changed from has-patch, 3.2-early to has-patch 3.2-early

edit: not sure why its playing with the keywords

Last edited 12 years ago by jaredatch (previous) (diff)

#11 @scribu
12 years ago

  • Keywords 2nd-opinion added; 3.2-early removed

#12 @nacin
10 years ago

  • Component changed from Template to Posts, Post Types
  • Focuses template added

#13 @obenland
10 years ago

There is a way to retrieve a custom field value that is somewhat agnostic of current context: post_custom() (#).

I suppose we could introduce a function that is a bit more coherent with the naming conventions of template tags, and which optionally also accepts a post id:

<?php
/**
 * Retrieve the value for a post meta field.
 *
 * @since 4.0.0
 *
 * @param string $key The meta key to retrieve.
 * @param int $post_id Optional. Post ID. 
 *
 * @return mixed The value of meta data field or an empty string.
 */
function get_post_meta_value( $key, $post_id = 0 ) {
        return get_post_meta( get_post( $post_id )->ID, $key, true );
}

But one could make the argument that it is not strictly necessary. If they're looking for a meta value of a specific post, they can use get_post_meta(). If they're looking for a meta value of the current post, they can use post_custom().

Last edited 10 years ago by obenland (previous) (diff)

#14 @wonderboymusic
9 years ago

  • Keywords 2nd-opinion removed
  • Owner changed from filosofo to obenland
  • Status changed from new to assigned

Do you want to do anything here?

#15 @swissspidy
7 years ago

  • Keywords needs-unit-tests dev-feedback added

#16 @costdev
20 months ago

As mentioned by @obenland in comment 13, post_custom() is already available.

There is also get_post_custom_values(), which returns an array of values for the given field.

Following that, this works:

<?php
function get_post_custom_value( $key = '', $post_id = 0 ) {
        $value = get_post_custom_values( $key, $post_id );
        return $value ? maybe_unserialize( $value[0] ) : null;
}

// Usage
var_dump( get_post_custom_value( 'my_custom_field' ) );
  • Is consistent with existing naming i.e. post_custom(), get_post_custom(), get_post_custom_values().
  • Lets get_post_custom() handle checks on $post_id.
  • Reduces maintenance.
  • Reduces the number of unit tests required.

However, get_post_custom_values() is in use by 789 plugins and 140 themes.

While I don't have the strict number of plugins and themes using get_post_meta() - because I don't want to write the regex for excluding default meta fields 😝 - a cursory glance at plugins using get_post_meta() ref and plugins using get_post_meta( get_the_ID()... ref suggests that get_post_meta() is used significantly more often for custom fields - likely for the reasons mentioned in this ticket's description.

Therefore, do we:

  • as the current patch does, introduce a new function that also tries to use the current queried object and has a name more consistent with get_post_meta() in hopes it would make transitioning more likely.
  • introduce something like get_post_custom_value() above for consistency with the already available functions, since any new function will be mentioned in a dev note anyway.
  • don't introduce a new function, as the community already widely uses get_post_meta() and adding a new function might just introduce another asset for the BC-promise?
Note: See TracTickets for help on using tickets.