'Adding Multiple Custom Post Types in Wordpress

I was fine with adding one custom post type (releases) to my functions.php file, but then adding a second (projects) seems to have complicated things.

The problem i'm getting is the url structure is not responding to the path mysite.com/projects/project-name (returns 404), whereas mysite.com/releases/release-name is working by calling the template content-single.php and archive-releases.php. I'm wondering if I've done something wrong in this function?

function custom_post_event() {
  $labels1 = array(
    'name'               => _x( 'Releases', 'post type general name' ),
    'singular_name'      => _x( 'Release', 'post type singular name' ),
    'add_new'            => _x( 'Add New', 'release' ),
    'add_new_item'       => __( 'Add New Releases' ),
    'edit_item'          => __( 'Edit Release' ),
    'new_item'           => __( 'New Release' ),
    'all_items'          => __( 'All Releases' ),
    'view_item'          => __( 'View Release' ),
    'search_items'       => __( 'Search Releases' ),
    'not_found'          => __( 'No release found' ),
    'not_found_in_trash' => __( 'No release found in the Trash' ), 
    'parent_item_coleon'  => '',
    'menu_name'          => 'Releases'
  );

   $labels2 = array(
    'name'               => _x( 'Projects', 'post type general name' ),
    'singular_name'      => _x( 'Project', 'post type singular name' ),
    'add_new'            => _x( 'Add New', 'project' ),
    'add_new_item'       => __( 'Add New Projects' ),
    'edit_item'          => __( 'Edit Project' ),
    'new_item'           => __( 'New Project' ),
    'all_items'          => __( 'All Projects' ),
    'view_item'          => __( 'View Project' ),
    'search_items'       => __( 'Search Projects' ),
    'not_found'          => __( 'No project found' ),
    'not_found_in_trash' => __( 'No projects found in the Trash' ), 
    'parent_item_coleon'  => '',
    'menu_name'          => 'Projects'
  );
  $args1 = array(
    'labels'        => $labels1,
    'description'   => 'Holds releases and release specific data',
    'public'        => true,
    'menu_position' => 5,
    'supports'      => array( 'title', 'editor', 'thumbnail', 'excerpt', 'custom-fields', 'comments' ),
    'has_archive'   => true,
  );

  $args2 = array(
    'labels'        => $labels2,
    'description'   => 'Holds projects and release specific data',
    'public'        => true,
    'menu_position' => 6,
    'supports'      => array( 'title', 'editor', 'thumbnail', 'excerpt', 'custom-fields', 'comments' ),
    'has_archive'   => true,
  );
  register_post_type( 'releases', $args1 ); 
  register_post_type( 'projects', $args2 ); 
}

add_action( 'init', 'custom_post_event' );


Solution 1:[1]

First of all, if you haven't saved permalinks, go ahead and do it by going to Settings->Permalinks->Save Settings.

content-single.php template file should load a single project fine, however, you can also create single-projects.php file inside the theme folder and use it as an alternative.

archive-releases.php isn't gonna show the projects archive page. You'll have to create archive-projects.php inside the theme folder for that.


Please check this https://developer.wordpress.org/themes/basics/template-hierarchy/ page for a better understanding of how WordPress uses the theme template files to show different pages.

Thanks.

Solution 2:[2]

A more straightforward method to avoid repetition will be to write one function to set up and register multiple post types from a single action, add_action( 'init', 'custom_cpts' );. The function's argument can be modified as you deem fit.

STEP 1

function create_post_type(  string $singular = 'Customer', 
                            string $plural = 'Customers', 
                            string $menu_icon = 'dashicons-carrot',
                            bool $hierarchical = FALSE, 
                            bool $has_archive = TRUE, 
                            string $description = '' ) {
        //Here, the default post type if no argument is passed to create_post_type() will be Customer CPT

        register_post_type( $singular, array(
        'public'            => TRUE,
        'show_in_rest'      => TRUE,
        'description'       => $description,
        'menu_icon'         => $menu_icon,
        'hierarchical'      => $hierarchical,
        'has_archive'       => $has_archive,
        'supports'          => array('title', 'editor', 'author', 'excerpt', 'page-attributes', 'thumbnail', 'custom-fields', 'comments'),
        'labels' => array(
            'name'                      => $plural,
            'singular_name'             => $singular,
            'add_new'                   => 'Add New '.$singular,
            'add_new_item'              => 'New '.$singular,
            'edit_item'                 => 'Edit '.$singular,
            'view_item'                 => 'View '.$singular,
            'view_items'                => 'View '.$plural,
            'search_items'              => 'Search '.$plural,
            'not_found'                 => 'No '.$plural.' Found',
            'all_items'                 => 'All '.$plural,
            'archives'                  => $plural.' Archives',
            'attributes'                => $singular.' Attributes',
            'insert_into_item'          => 'Insert into '.$singular,
            'uploaded_to_this_item'     => 'Uploaded to this '.$singular,
            'featured_image'            => $singular.' Featured image',
            'set_featured_image'        => 'Set '.$singular.' featured image',
            'remove_featured_image'     => 'Remove '.$singular.' featured image',
            'use_featured_image'        => 'Use as '.$singular.' featured image',
            'filter_items_list'         => 'Filter '.$plural.' list',
            'filter_by_date'            => 'Filter '.$plural.' by date',
            'items_list_navigation'     => $plural.' list navigation',
            'items_list'                => $plural.' list',
            'item_published'            => $singular.' published.',
            'item_published_privately'  => $singular.' published privately.',
            'item_reverted_to_draft'    => $singular.' reverted to draft.',
            'item_scheduled'            => $singular.' scheduled.',
            'item_updated'              => $singular.' updated.',
            'item_link'                 => $singular.' link'
        ),

        'rewrite'           => array(
            'slug'                      => strtolower($plural),
            'pages'                     => TRUE,
        )
    ));
    
}
function custom_cpts() {
    create_post_type('Project', 'Projects','dashicons-excerpt-view');
    create_post_type('Release', 'Releases', 'dashicons-unlock');
    create_post_type('Event', 'Events','dashicons-calendar');
}

add_action( 'init', 'custom_cpts' );
?>

STEP 2 Now, go to: Settings->Permalinks in your admin area. Then click the Save button on the Settings view.

STEP 3 Create the corresponding template files based on the naming convention {{template_type}}-{{cpt-name}}.php in your directory. For example: single-release.php or single-project.php

archive-project.php
single-project.php
archive-release.php
single-release.php

That's it!

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 gjzim
Solution 2 Tamara