Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I've setup a custom post type with a series of custom fields using the WPAlchemy class. I'm trying to take the value of one of the custom fields and use that as the post title. So far, though, I've had no success. I've been browsing around and I've tried the following two different blocks of code:

function custom_post_type_title ( $post_id ) {
    global $wpdb;
    if ( get_post_type( $post_id ) == 'listing' ) {
        $title = get_post_meta($post_id, 'listing_name', true);
        $where = array( 'ID' => $post_id );
        $wpdb->update( $wpdb->posts, array( 'post_title' => $title ), $where );

add_action('init', 'listing_save_post');
function listing_save_post( $post_id ) {
        if ( ! defined( 'DOING_AUTOSAVE' ) && ! DOING_AUTOSAVE ) return;
        add_action('save_post', 'custom_post_type_title', 100);
        add_action('publish_post', 'custom_post_type_title', 100);

And.. (temporarily commenting out the nonce fields until I figure out how they work)

add_filter('wp_insert_post_data', 'change_title', 99, 2);
function change_title($data, $postarr)
    // If it is our form has not been submitted, so we dont want to do anything
    if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;

    // Verify this came from the our screen and with proper authorization because save_post can be triggered at other times
   // if(!isset($_POST['my_nonce_field'])) return;

    // If nonce is set, verify it
   // if(isset($_POST['my_nonce_field']) && !wp_verify_nonce($_POST['my_nonce_field'], plugins_url(__FILE__))) return;

       // Combine address with term
    $title = $_POST['listing_name'];
    $data['post_title'] = $title;

    return $data;

In both cases, the results are the same:

  1. On saving the new post, it reloads the page, says it worked, and all of the custom fields are empty. (Without either code set running, the custom post works just fine and the fields are saved).

  2. On viewing the custom post type index, the posts aren't there.

Any ideas?


To clarify, I am using a custom post without the title support. I am trying to populate the title field nonetheless, though, using the value in the custom field.

share|improve this question

1 Answer 1

up vote 3 down vote accepted

So, every time you save a post, you want to replace the value of a title that just got saved with another value from a custom field...

Seems like you should just put whatever you what the title to be in the actual title field.

BUT I'm assuming this is for presentational purposes: you want that custom post type to display a different title on the front end based on the value of a custom field. Filters would be an easy way to accomplish this.

the_title, the common template tag, is a very thin wrapper around get_the_title, which contains a filter called the_title. It gets two arguments: the actual title and the post ID. Hook into that and change the title based on your custom field.

add_filter( 'the_title', 'wpse33385_filter_title', 10, 2 );
function wpse33385_filter_title( $title, $post_id )
    if( $new_title = get_post_meta( $post_id, 'custom_field_name', true ) )
        return $new_title;
    return $title;

A few things about your code to keep in mind:

Actions don't arbitrarily receive arguments. Functions hooked into init for example, don't get any arguments passed to them. when do_action is called, the first argument is a hook name. Subsequent arguments are what gets passed to hooked in functions if you desire (specified by the fourth, option arguments of add_action).

the do_action( 'init' ); call is in wp-settings.php. Take a look, no arguments.

So this:

add_action('init', 'listing_save_post');
function listing_save_post( $post_id ) {
        if ( ! defined( 'DOING_AUTOSAVE' ) && ! DOING_AUTOSAVE ) return;
        add_action('save_post', 'custom_post_type_title', 100);
        add_action('publish_post', 'custom_post_type_title', 100);

Is not going to work like you expect. Moreover, the add_action calls inside the function, can just be on their own outside the function... This works fine:

add_action('save_post', 'custom_post_type_title', 100);
function custom_post_type_title( $post_id ) {
    // do stuff

Only need to do stuff on save_post, not on that and publish_post

I always try to avoid going directly to $wpdb if I can, because many times there are more convenient APIs. What you were trying to do is updated a post. So use wp_update_post. In your case, that's not a valid option (as the codex states, it can cause an infinite loop).

That was kind of long winded, sorry. Hopefully it cleared up some things about the WordPress hooks system!

Make these your best friends:

share|improve this answer
Christopher, thank you for the detailed thoughts! I'll go through and soak them in more thoroughly. To clarify, though, I am actually trying to pull off a custom post type without using the title field and then have a title show up (made up of a custom field), on the front end, and in the backend (in the list of custom posts). Does that clarify? –  Jonathan Wold Nov 10 '11 at 17:21
The filter thing I showed you will work for that. If you want to get rid of the title field entirely, there's an argument in the $args array for register_post_type called post_type_supports, set it like this 'post_type_supports' => array( 'content' ), no more title on the editing screen. –  chrisguitarguy Nov 10 '11 at 19:47
That worked! So, I'm using a filter, then to pull off the desired effect. If I were to try and retrieve the value, say via WPDB, of the post_title field, I would get the "auto draft" value - correct? The "purist" in me wants to fix that, though I get that the "filter" works. Any thoughts? THANK YOU for the help! –  Jonathan Wold Nov 11 '11 at 2:05

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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