WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I had this working a couple of weeks ago and the only thing I can think is that WordPress has updated and broken the functionality?

I followed the tutorial here to add custom fields: http://net.tutsplus.com/tutorials/wordpress/rock-solid-wordpress-3-0-themes-using-custom-post-types/

It was working fine (I entered about 50 custom posts all with custom fields) but when I go to edit it today any changes I make to the custom fields are not being saved, although other changes work fine.

Does anyone know if this is a known bug?

Edit: Here is the code, added in functions.php to a brand new install (theme: twentyten)

add_action('init', 'testimonials_register');
add_action("admin_init", "admin_init");
add_action('save_post', 'save_testimonial');

function testimonials_register() {
    $args = array(
        'label' => __('Testimonials'),
        'singular_label' => __('Testimonial'),
        'public' => true,
        'show_ui' => true,
        'capability_type' => 'post',
        'menu_position' => 5,
        'hierarchical' => false,
        'rewrite' => true,
        'supports' => array('title', 'editor', 'thumbnail','custom-fields', 'revisions', 'excerpt', 'page-attributes')

    register_post_type( 'testimonials' , $args );

register_taxonomy( 'testimonial_project_type', array("testimonials") , array( 'hierarchical' => true, 'label' => 'Project Type', 'query_var' => true, 'rewrite' => true ) );

function admin_init(){
    add_meta_box("testimonialInfo-meta", "Testimonial Options", "meta_options_testimonial", "testimonials", "advanced", "high");


function meta_options_testimonial(){
    global $post;
    $custom = get_post_custom($post->ID);
    $name = $custom["name"][0];
    $position = $custom["position"][0];
    $project_url = $custom["project_url"][0];
    $website = $custom["website"][0];
  <label for="name" style="width:90px;display:inline-block">Name:</label> <input size="50" name="name" id="name" value="<?php echo $name; ?>" /><br>
  <label for="position" style="width:90px;display:inline-block">Position:</label> <input size="50" name="position" id="position" value="<?php echo $position; ?>" /><br>
  <label for="website" style="width:90px;display:inline-block">Website Name:</label> <input size="50" name="website" id="website" value="<?php echo $website; ?>" /><br>
  <label for="project_url" style="width:90px;display:inline-block">Project slug:</label> <input size="50" name="project_url" id="project_url" value="<?php echo $project_url; ?>" /> <small>E.g. 'parker-harris'</small><br>

    function save_testimonial(){
$custom_meta_fields = array( 'project_url','name','position','website');
foreach( $custom_meta_fields as $custom_meta_field ):
    if(isset($_POST[$custom_meta_field]) && $_POST[$custom_meta_field] != ""):
        update_post_meta($post->ID, $custom_meta_field, $_POST[$custom_meta_field]);


    add_filter("manage_edit-testimonials_columns", "testimonials_edit_columns");  
    add_action("manage_posts_custom_column",  "testimonials_custom_columns");  

    function testimonials_edit_columns($columns){  
    $columns = array(  
        "cb" => "<input type=\"checkbox\" />",  
        "title" => "Testimonial Title",  
        "name" => "Name",  
        "description" => "Excerpt",  
        "project_url" => "Project Slug"

    return $columns;  

    function testimonials_custom_columns($column){  
    global $post;  
    switch ($column)  
        case "name":  
            $custom = get_post_custom();  
            echo $custom["name"][0].", ".$custom["position"][0]."<br> ".$custom["website"][0];
        case "description":  
        case "project_url":  
            $custom = get_post_custom();  
            echo "<a target='_blank' href='/portfolio/".$custom["project_url"][0]."'>".$custom["project_url"][0]."</a>";

    // This shows testimonials in blog and feed.

    add_filter( 'pre_get_posts', 'my_get_posts' );

    function my_get_posts( $query ) {

if ( is_home() && false == $query->query_vars['suppress_filters']  || is_feed() )
    $query->set( 'post_type', array( 'post', 'testimonials') );

return $query;
share|improve this question
By the way, this is NOT the other saving problem which has cropped up from those tutorials (Autosaving wiping out the data) as I fixed that and this does not save it at all, nit just on a timer. But it was working fully just a few weeks ago! – Shaun Oct 27 '10 at 23:01
My custom post types work just fine. Instead of linking us to the tutorial please provide a link to your code in something like pastie.org or gist.github.com then we can dig through your code. – curtismchale Oct 28 '10 at 1:57
up vote 2 down vote accepted

I put your code in a plugin and had to change two things to get it working:

  • In save_testimonial(), you use $post but don't declare it as a global. So $post->ID will be empty, and update_post_meta() does not know what to save. Add global $post; at the beginning of the function.
  • register_taxonomy() is not in your init handler, and is probably called too early (if it is a plugin, maybe you were lucky when you did this in functions.php). Move it to the testimonals_register() function.

Did you have WP_DEBUG set to TRUE when you were debugging it? Then you should have gotten the warnings that lead me to this solution.

share|improve this answer
Thanks, that worked! It must have been removed from the code somehow... :) – Shaun Oct 28 '10 at 11:44

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.