Wordpress - Change slug on post creation
Here is what I did to implement this:
function slug_save_post_callback( $post_ID, $post, $update ) {
// allow 'publish', 'draft', 'future'
if ($post->post_type != 'post' || $post->post_status == 'auto-draft')
return;
// only change slug when the post is created (both dates are equal)
if ($post->post_date_gmt != $post->post_modified_gmt)
return;
// use title, since $post->post_name might have unique numbers added
$new_slug = sanitize_title( $post->post_title, $post_ID );
$subtitle = sanitize_title( get_field( 'subtitle', $post_ID ), '' );
if (empty( $subtitle ) || strpos( $new_slug, $subtitle ) !== false)
return; // No subtitle or already in slug
$new_slug .= '-' . $subtitle;
if ($new_slug == $post->post_name)
return; // already set
// unhook this function to prevent infinite looping
remove_action( 'save_post', 'slug_save_post_callback', 10, 3 );
// update the post slug (WP handles unique post slug)
wp_update_post( array(
'ID' => $post_ID,
'post_name' => $new_slug
));
// re-hook this function
add_action( 'save_post', 'slug_save_post_callback', 10, 3 );
}
add_action( 'save_post', 'slug_save_post_callback', 10, 3 );
It generates and updates the slug
. Previous slug generated by WP can not be reused since it can have unique numbers if the title/slug was already used in another post. So, I sanitize the title. Then, wp_update_post
makes sure there are no duplicates for the new slug with wp_unique_post_slug
.
The only way I could find to only do this on publish is to compare the creation and the modified time. They are only equal when the post is created. The $update
parameter is useless, since is true
for the publish.