A common problem wordpress developers run into when registering new custom post types (CPTs) is having incorrect arguments, that generate slugs, or public single instances of the post type, and then realizing it after registering the CPT, needing to go back to change the $args and not seeing the change updated. As an example, let’s say I register this post type: // this is for manually added testimonials add_action( 'init', 'testimonials_post_type', 0 ); function testimonials_post_type() { // Create labels for your custom fields $labels = array( 'name' => _x("Testimonials", "post type general name"), 'singular_name' => _x("Testimonial", "post type singular name"), 'menu_name' => 'Testimonials', 'add_new' => _x("Add New", "testimonial"), 'add_new_item' => __("Add New Testimonial"), 'edit_item' => __("Edit Testimonial"), 'new_item' => __("New Testimonial"), 'view_item' => __("View Testimonial"), 'search_items' => __("Search Testimonials"), 'not_found' => __("No Testimonials Found"), 'not_found_in_trash' => __("No Testimonials Found in Trash"), 'parent_item_colon' => '' ); // Register post type array for use. register_post_type('testimonials' , array( 'labels' => $labels, 'public' => true, 'has_archive' => false, 'menu_icon' => 'dashicons-format-quote', 'supports' => array('title', 'editor', 'thumbnail') ) ); }
You can see I set has_archive to false! But I then I realized I wanted to create an archive-testimonials.php template because my testimonials don’t all fit on my pretty homepage cpt loop section, so I’m just using excerpts on the homepage and then users can click through to read full testimonials on my archive page (or the client wants a /testimonials page). So I set it to “True”, create my archive-testimonials.php, put it in my theme folder, and go to clientsite.com/testimonials, but low and behold it throws a 404. This is because when you register a custom post type, wordpress uses your arguments to hard write your CPT configuration upon first registering the CPT. Otherwise you would be putting a ton of strain of writing/rewriting configurations for permalinks, etc., every time a user refreshes the page. The following code snippet and then switching themes to activate it works well to fix this issue. Uses example of a “projects” CPT. Replace accordingly. function projects_cpt_rewrite_flush() { global $wp_rewrite; $projects_structure = '/projects/%projects%/'; $wp_rewrite->add_rewrite_tag("%projects%", '([^/]+)', "projects="); $wp_rewrite->add_permastruct('projects', $projects_structure, false); } add_action( 'after_switch_theme', 'projects_cpt_rewrite_flush' );
for functions.php or bottom of home made register CPT type plugins It’s important here to use the after_switch_theme (then switch themes to activate), or a similar hook so that we aren’t flushing the configuration every pageload that relies on functions.php, or a plugin. That would be a no no.
Leave a Reply