Force post slug to be auto generated from title on save

I’m running a property site where many properties are sold in apartment blocks.

Because of this what the content editors do is create a post/property with all the details and then use a duplicate post plugin to create the others.

Read More

Each time they duplicate a post/property they change the title to reflect the property number and maybe change a few bits of meta data E.G price.

What they forget to do is wipe out the slug and let a new one be generated from the title. Here is an example slug from the first property entered:

merle-court-plot-50-182-carlton-vale-nw6-5hh

but then when they duplicate the slugs become:

merle-court-plot-50-182-carlton-vale-nw6-5hh-2
merle-court-plot-50-182-carlton-vale-nw6-5hh-2-2
merle-court-plot-50-182-carlton-vale-nw6-5hh-2-2-2
merle-court-plot-50-182-carlton-vale-nw6-5hh-2-2-2-2
etc

But when they change the titles the slugs would be better like:

merle-court-plot-51-182-carlton-vale-nw6-5hh
merle-court-plot-52-182-carlton-vale-nw6-5hh
merle-court-plot-53-182-carlton-vale-nw6-5hh
merle-court-plot-54-182-carlton-vale-nw6-5hh
etc

So my question:

How do I force the slug to be re-generated on post save, after they have updated the property title?

The slug for this CPT should always be auto generated, there is never a need to manually set it.

Related posts

Leave a Reply

4 comments

  1. The easiest workaround could be:

    function myplugin_update_slug( $data, $postarr ) {
        if ( ! in_array( $data['post_status'], array( 'draft', 'pending', 'auto-draft' ) ) ) {
            $data['post_name'] = sanitize_title( $data['post_title'] );
        }
    
        return $data;
    }
    add_filter( 'wp_insert_post_data', 'myplugin_update_slug', 99, 2 );
    
  2. Instead of replacing spaces you should use the build in function sanitize_title() which will take care of the replacing for you.

    Like this:

    sanitize_title( $post_title, $post->ID );
    

    Also, you should use a unique slug. Which you can get with the function wp_unique_post_slug()

    So putting it all together a solution might be:

    function myplugin_update_slug( $data, $postarr ) {
        if ( ! in_array( $data['post_status'], array( 'draft', 'pending', 'auto-draft' ) ) ) {
            $data['post_name'] = wp_unique_post_slug( sanitize_title( $data['post_title'] ), $postarr['ID'], $data['post_status'], $data['post_type'], $data['post_parent'] );
        }
    
        return $data;
    }
    add_filter( 'wp_insert_post_data', 'myplugin_update_slug', 99, 2 );
    
  3. Something I’ve had bookedmarked for a little while is the following (yet untested),

    Source LINK

    //add our action
    add_action( 'save_post', 'my_save_post', 11, 2 );
    
    function my_save_post($post_id, $post){
    
       //if it is just a revision don't worry about it
       if (wp_is_post_revision($post_id))
          return false;
    
       //if the post is an auto-draft we don't want to do anything either
       if($post->post_status != 'auto-draft' ){
    
           // unhook this function so it doesn't loop infinitely
           remove_action('save_post', 'my_save_post' );
    
          //this is where it happens -- update the post and change the post_name/slug to the post_title
          wp_update_post(array('ID' => $post_id, 'post_name' => str_replace(' ', '-', $_POST['post_title'])));
    
          //re-hook this function
          add_action('save_post', 'my_save_post' );
       }
    }