• Resolved TWD

    (@twd)


    I have a custom post type called “Clients”.
    And a custom field “Client ID” (integer)

    The first time a new Client record is created, I want WordPress
    to loop through all the Client records created so far, find the highest “Client ID” value, increment it by “1”, then save that value into the Client ID field.

    So far, so good.

    But anytime somebody goes back and “updates” this post, it will generate a new Client ID value. Not good.

    So the solution would seem to be, to limit the “loop, increment, save” function to only happen when the post is first created, and NOT when the post is updated.

    Any ideas how to do that?

Viewing 9 replies - 1 through 9 (of 9 total)
  • wp_insert_post hook has a paramter which specifies whether it is be run only on post creation or post updation as well.

    do_action( 'wp_insert_post', int $post_ID, WP_Post $post, bool $update )

    So, you will need to run your code only if $update is false

    Thread Starter TWD

    (@twd)

    Back to first principles.
    I would expect this code to insert the value ‘1234’ on update.
    But nothing happens.
    Yes, I am a coding noob.

    function set_external_client_id( $post_id, $post ){
        
        if ( 'auction-client' == $post->post_type ) {
            //only proceed if this is a Client post type
            
            do_action( 'wp_insert_post', $post_id, $post, $update );
            if($update){
                $external_client_id = 1234;
                update_post_meta( $post_id, 'wpcf-external-client-id', $external_client_id);
            }       
                
        }
    }
    add_action( 'save_post', 'set_external_client_id', 30, 2 );
    function set_external_client_id( $post_id, $post, $update ) {
    	if ( wp_is_post_revision( $post_id ) ) {
            return;
    	}
    
    	if ( 'auction-client' == $post->post_type ) {
    		if( !$update ){
                $external_client_id = 1234;
                update_post_meta( $post_id, 'wpcf-external-client-id', $external_client_id);
            }
    	}
    }
    add_action( 'wp_insert_post', 'set_external_client_id', 10, 3 );
    Thread Starter TWD

    (@twd)

    Thank you.
    That works!

    Now to expand on that to address the initial problem, how to find the highest External Client ID, increment it by “1” and save that value when the post is created (but not when updated).

    Can you tell me what mistake I have made with this code?

    The value is always saved as “1”.

    function set_external_client_id( $post_id, $post, $update ) {
    	if ( wp_is_post_revision( $post_id ) ) {
            return;
    	}
    
    	if ( 'auction-client' == $post->post_type ) {
    		if( !$update ){
                $args = array(  
                    'post_type' => 'auction-client',
                    'post_status' => 'publish',
                );
                $loop = new WP_Query( $args ); 
                
                $find_highest_id = 0;
                while ( $loop->have_posts() ) : $loop->the_post(); 
                    $external_client_id = get_post_meta( $post_id, 'wpcf-external-client-id', true );
                    if($external_client_id > $find_highest_id){
                        $find_highest_id = $external_client_id;
                    }
                endwhile;
                
                $external_client_id = $find_highest_id + 1;
                update_post_meta( $post_id, 'wpcf-external-client-id', $external_client_id);
            }
    	}
    }
    add_action( 'wp_insert_post', 'set_external_client_id', 10, 3 );

    The problem is in your get_post_meta.

    Your code is:
    get_post_meta( $post_id, 'wpcf-external-client-id', true );

    In the first parameter, you have incorrectly passed $post_id which is the ID of the newly created post.
    You should pass the ID of the post in the loop. So, use get_the_ID() instead.

    Sidenote:
    1. You should use wp_reset_postdata() after the while loop

    2. You could also have the WP_Query so that the results are displayed in descending order of the value of the meta field.

    
    $args = array(
        'post_type' => 'auction-client',
        'post_status' => 'publish',
        'meta_key' => 'wpcf-external-client-id',
        'orderby' => 'meta_value_num',
        'order' => 'DESC'
    );
    

    This way the first post in the loop will be the one with the highest value of ‘wpcf-external-client-id’. So you won’t need to loop through all the results; you’d be able to use just the first one.

    • This reply was modified 3 years, 9 months ago by Shariq Khan.
    Thread Starter TWD

    (@twd)

    Terrific answer.
    Thank you for taking the time to explain this.
    That’s how others can learn!

    You said:
    “2. You could also have the WP_Query so that the results are displayed in descending order of the value of the meta field.”

    I actually thought about this.
    Is it MORE efficient to ask PHP to sort the results and then just pick the first result of the array? OR is it more efficient to loop through as I have done?

    “This way the first post in the loop will be the one with the highest value of ‘wpcf-external-client-id’. So you won’t need to loop through all the results; you’d be able to use just the first one.”

    BTW could you just remind me how to access the first post?
    This would be an array of “post objects” correct?

    Is it MORE efficient to ask PHP to sort the results and then just pick the first result of the array?

    In this case, it will be MySQL that will be doing the sorting. So you are offloading the task of sorting to mySQL , instead of having PHP do it. And will be a bit faster, compared to let PHP do the sorting.

    BTW could you just remind me how to access the first post?

    Try this:

    
    $loop = new WP_Query( $args ); 
    $posts = $loop->posts;
    
    $first_post = $posts[0];
    
    Thread Starter TWD

    (@twd)

    Thank you so much for all your help.
    REALLY appreciate it.
    I’m going to stick with my PHP approach for now, since its only a smallish number of records.

    Here is the final code:

    // only create a new external client ID if the post in new, NOT an update
    function set_external_client_id( $post_id, $post, $update ) {
    	if ( wp_is_post_revision( $post_id ) ) {
            return;
    	}
    
    	if ( 'auction-client' == $post->post_type ) {
    		if( !$update ){
                $args = array(  
                    'post_type' => 'auction-client',
                );
                $myloop = new WP_Query( $args );
                
                //loop through all posts of this post type to find the highest client id
                $find_highest_id = 0;
                while ( $myloop->have_posts() ) : $myloop->the_post();
                    $this_post_id = get_the_ID();
                    $external_client_id = get_post_meta( $this_post_id, 'wpcf-external-client-id', true );
                    if($external_client_id > $find_highest_id){
                        $find_highest_id = $external_client_id;
                    }
                endwhile;
                wp_reset_postdata();
                
                //take the highest value and increment it then save as client id for the new client
                $external_client_id = $find_highest_id + 1;
                update_post_meta( $post_id, 'wpcf-external-client-id', $external_client_id);
            }
    	}
    }
    add_action( 'wp_insert_post', 'set_external_client_id', 10, 3 );
    Thread Starter TWD

    (@twd)

    Resolved.

Viewing 9 replies - 1 through 9 (of 9 total)
  • The topic ‘How to run a code snippet ONLY when a post is created, not when updated’ is closed to new replies.