If you start to edit a new post, already a post with the status auto-draft
is created. Actually, what you see is this post. So you can hook into the transition filter new_to_auto-draft
and add a category to this post:
add_action( 'new_to_auto-draft', function( $post ) {
// Bail out, if not in admin editor.
if ( ! strpos( $_SERVER['REQUEST_URI'], 'wp-admin/post-new.php' ) ) {
return;
}
// Bail out, it no category set in $_GET.
if ( empty( $_GET['cat'] ) ) {
return;
}
$cat = wp_unslash( $_GET['cat'] );
// Bail out, if category does not exist.
if ( false === ( $cat = get_category_by_slug( $cat ) ) ) {
return;
}
wp_set_post_categories( $post->ID, array( $cat->term_id ) );
} );
Explanation
As I’ve said, a post is created in the moment, you open the editor. wp_insert_post()
is calling wp_transition_post_status( $new_status, $old_status, $post )
where the $new_status is auto-draft
and the old “status” is new
. wp_transition_post_status()
basically fires three action hooks:
I am using {$old_status}_to_{$new_status}
(new_to_auto-draft
) because it is the most precise for what you are trying to accomplish.
In the function, where we get the post object as parameter ($post
), we bail out if we are not in the correct location or the $_GET['cat']
is not found. With wp_unslash()
we remove ‘\’ and stuff from $_GET['cat']
. Another possibility would be to use sanitize_key()
, maybe it is even more appropriate.
We now load the category object with get_category_by_slug()
since we will need the ID of the category to attach the post to the category in wp_set_post_categories()
. If the category was not found get_category_by_slug()
will return false
and we bail out. Another idea would be to create a category with this slug, if the category was not found.
For Custom Post Types and Custom Taxonomies
In response to
This does not seem to work on a custom post type/taxonomy
The above example works explicitly on the post type post
and the taxonomy category
. If you want to use it with a custom post type and a custom taxononmy, you will need to use get_term_by()
instead of get_category_by_slug()
and you will need to use wp_set_object_terms()
instead of wp_set_post_categories()
.
The example below registers a post type, a taxonomy and shows the process:
add_action( 'new_to_auto-draft', function( $post ) {
// Bail out, if not in admin editor.
if ( ! strpos( $_SERVER['REQUEST_URI'], 'wp-admin/post-new.php' ) ) {
return;
}
// Bail out, it no category set in $_GET.
if ( empty( $_GET['post_type'] ) || 'post_slug' !== wp_unslash( $_GET['post_type'] ) ) {
return;
}
// Bail out, it no category set in $_GET.
if ( empty( $_GET['cat'] ) ) {
return;
}
$cat = wp_unslash( $_GET['cat'] );
// Bail out, if category does not exist.
if ( false === ( $cat = get_term_by( 'slug', $cat, 'tax' ) ) ) {
return;
}
wp_set_object_terms( $post->ID, array( $cat->term_id ), 'tax' );
} );
add_action ( 'init', function() {
$args['label'] = 'Test';
$args['public'] = TRUE;
register_post_type( 'post_slug', $args );
$args['label'] = 'Taxonomy';
register_taxonomy( 'tax', 'post_slug', $args );
});