Hook when Post created

alexy

Active Member
120
2022
49
8,790
Hi everyone,

I have added these codes in functions.php

Code:
function assign_post_to_category($post_id, $post, $update) {
    // Run only when a new post is created, not when updated
    if (get_post_type($post_id) !== 'post') {
        return;
    }

    $post_title = get_the_title($post_id); // Get post title

    // Split the title by the dot (.)
    $title_parts = explode('.', $post_title);

    // Get the first part
    $first_word = trim($title_parts[0]);

    $category_name = trim($title_parts[0]); // Change this to your desired category name

    // Check if the category exists
    $category_id = get_term_by('name', $category_name, 'category');
    
    // If category doesn't exist, create it
    if (!$category_id) {
        $category_id = wp_insert_term($category_name, 'category');
        if (is_wp_error($category_id)) {
            return; // If there's an error, stop execution
        }
        $cat = get_term_by( 'name', $category_name, 'category' );
        $category_id = $cat->term_id;
    } else {
        $category_id = $category_id->term_id;
    }

    $extra_categories = [$category_id];
    
    // Get current categories
    $existing_categories = wp_get_post_categories($post_id);
    
    // Assign the post to the category
   // Merge and set categories
    wp_set_post_categories($post_id, array_unique(array_merge($existing_categories, $extra_categories)));
}

add_action('publish_post', 'assign_post_to_category');

What I want to achieve is that I want to assign post to new/existing category.

But it seems, code can create new category but not assign post to it.

Can you please review and share what I'm doing wrong?

Thank you
 
3 comments
The problem isn't with creating the category (which actually works), but rather with the moment the assignment takes place.
You are using the `publish_post` hook. When you save a post from the block editor (Gutenberg), the save process goes through the REST API, and the sequence is as follows:

WordPress calls `wp_insert_post()`; this triggers `publish_post`, and your code correctly sets the categories;
immediately afterwards, the REST controller calls `handle_terms()`, which overwrites the post's taxonomies based on what the editor sent (usually just "Uncategorized").

So, your `wp_set_post_categories()` executes, but it gets overwritten a moment later. That is why the category is created but the post ends up unassigned. (Your code would work with the Classic Editor, which confirms this diagnosis.)
The solution is to hook into `wp_after_insert_post`, which was introduced specifically for this purpose: it runs after the post, terms, and meta data have been permanently saved, in both the classic and REST workflows.
Here is the complete, ready-to-use file:
Code:
function assign_post_to_category( $post_id, $post, $update, $post_before ) {
    // Skip autosaves and revisions
    if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ) {
        return;
    }

    // Only for published posts
    if ( $post->post_type !== 'post' || $post->post_status !== 'publish' ) {
        return;
    }

    // Uncomment if you want it to run only on newly created posts
    /*
    if ( $update ) {
        return;
    }
    */

    $post_title = $post->post_title;

    if ( empty( $post_title ) ) {
        return;
    }

    // Get the part before the first dot
    $title_parts   = explode( '.', $post_title );
    $category_name = trim( $title_parts[0] );

    if ( $category_name === '' ) {
        return;
    }

    // Check if the category already exists
    $term = get_term_by( 'name', $category_name, 'category' );

    if ( ! $term ) {
        // Create the category if it doesn't exist
        $new_term = wp_insert_term( $category_name, 'category' );

        if ( is_wp_error( $new_term ) ) {
            return;
        }

        $category_id = (int) $new_term['term_id'];
    } else {
        $category_id = (int) $term->term_id;
    }

    // Merge with existing categories and assign
    $existing   = wp_get_post_categories( $post_id );
    $categories = array_unique( array_merge( $existing, array( $category_id ) ) );

    wp_set_post_categories( $post_id, $categories );
}

add_action( 'wp_after_insert_post', 'assign_post_to_category', 10, 4 );
 
Back
Top