I have a client side web application which is loaded for two post types: /tutorial
and /dashboard
. WordPress routing works fine for the individual posts: /tutorial/tutorial-1
and /dashboard/dashboard-1
.
However, in my client side app, I want to handle additonal route fragments: /tutorial/tutorial-1/quiz
. My React router handles the URL fine when loaded, but when directly linked WordPress is giving a 404 because although a permalink for /tutorial/tutorial-1
exists, it can't match the last fragment.
I am assuming I need to do a rewrite rule, but it has been a long time since I wrote those for Apache. Basically I need to match /[post-type]/*
to route to the post type.
As requested post type registration:
$args = array (
'label' => esc_html__( 'Tutorials', 'tutorial' ),
'labels' => array(
'menu_name' => esc_html__( 'Tutorials', 'tutorial' ),
'name_admin_bar' => esc_html__( 'Tutorial', 'tutorial' ),
'add_new' => esc_html__( 'Add new', 'tutorial' ),
'add_new_item' => esc_html__( 'Add new Tutorial', 'tutorial' ),
'new_item' => esc_html__( 'New Tutorial', 'tutorial' ),
'edit_item' => esc_html__( 'Edit Tutorial', 'tutorial' ),
'view_item' => esc_html__( 'View Tutorial', 'tutorial' ),
'update_item' => esc_html__( 'Update Tutorial', 'tutorial' ),
'all_items' => esc_html__( 'All Tutorials', 'tutorial' ),
'search_items' => esc_html__( 'Search Tutorials', 'tutorial' ),
'parent_item_colon' => esc_html__( 'Parent Tutorial', 'tutorial' ),
'not_found' => esc_html__( 'No Tutorials found', 'tutorial' ),
'not_found_in_trash' => esc_html__( 'No Tutorials found in Trash', 'tutorial' ),
'name' => esc_html__( 'Tutorials', 'tutorial' ),
'singular_name' => esc_html__( 'Tutorial', 'tutorial' ),
),
'public' => true,
'exclude_from_search' => false,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_nav_menus' => true,
'show_in_admin_bar' => false,
'show_in_rest' => true,
'capability_type' => 'post',
'hierarchical' => false,
'has_archive' => true,
'query_var' => true,
'can_export' => true,
'rewrite_no_front' => false,
'supports' => array(
'title',
'editor',
'thumbnail',
'excerpt',
'comments',
'revisions',
),
'description' => 'A tutorial',
'menu_position' => 20,
'menu_icon' => 'dashicons-exerpt-view',
'rewrite' => true,
'show_in_graphql' => true,
'graphql_single_name' => 'tutorial',
'graphql_plural_name' => 'tutorials',
);
register_post_type( 'tutorial', $args );
I have a client side web application which is loaded for two post types: /tutorial
and /dashboard
. WordPress routing works fine for the individual posts: /tutorial/tutorial-1
and /dashboard/dashboard-1
.
However, in my client side app, I want to handle additonal route fragments: /tutorial/tutorial-1/quiz
. My React router handles the URL fine when loaded, but when directly linked WordPress is giving a 404 because although a permalink for /tutorial/tutorial-1
exists, it can't match the last fragment.
I am assuming I need to do a rewrite rule, but it has been a long time since I wrote those for Apache. Basically I need to match /[post-type]/*
to route to the post type.
As requested post type registration:
$args = array (
'label' => esc_html__( 'Tutorials', 'tutorial' ),
'labels' => array(
'menu_name' => esc_html__( 'Tutorials', 'tutorial' ),
'name_admin_bar' => esc_html__( 'Tutorial', 'tutorial' ),
'add_new' => esc_html__( 'Add new', 'tutorial' ),
'add_new_item' => esc_html__( 'Add new Tutorial', 'tutorial' ),
'new_item' => esc_html__( 'New Tutorial', 'tutorial' ),
'edit_item' => esc_html__( 'Edit Tutorial', 'tutorial' ),
'view_item' => esc_html__( 'View Tutorial', 'tutorial' ),
'update_item' => esc_html__( 'Update Tutorial', 'tutorial' ),
'all_items' => esc_html__( 'All Tutorials', 'tutorial' ),
'search_items' => esc_html__( 'Search Tutorials', 'tutorial' ),
'parent_item_colon' => esc_html__( 'Parent Tutorial', 'tutorial' ),
'not_found' => esc_html__( 'No Tutorials found', 'tutorial' ),
'not_found_in_trash' => esc_html__( 'No Tutorials found in Trash', 'tutorial' ),
'name' => esc_html__( 'Tutorials', 'tutorial' ),
'singular_name' => esc_html__( 'Tutorial', 'tutorial' ),
),
'public' => true,
'exclude_from_search' => false,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_nav_menus' => true,
'show_in_admin_bar' => false,
'show_in_rest' => true,
'capability_type' => 'post',
'hierarchical' => false,
'has_archive' => true,
'query_var' => true,
'can_export' => true,
'rewrite_no_front' => false,
'supports' => array(
'title',
'editor',
'thumbnail',
'excerpt',
'comments',
'revisions',
),
'description' => 'A tutorial',
'menu_position' => 20,
'menu_icon' => 'dashicons-exerpt-view',
'rewrite' => true,
'show_in_graphql' => true,
'graphql_single_name' => 'tutorial',
'graphql_plural_name' => 'tutorials',
);
register_post_type( 'tutorial', $args );
You can add an internal rewrite so WordPress recognizes these requests. In the same function hooked to init
where you add the post type, you can add:
add_rewrite_tag( '%tutorial_fragment%', '([^/]+)' );
add_rewrite_rule(
'tutorial/([^/]+)/([^/]+)/?$',
'index.php?tutorial=$matches[1]&tutorial_fragment=$matches[2]',
'top'
);
The value is available via the WP API after the request is parsed:
$value = get_query_var( 'tutorial_fragment' );
After any changes to rules, flush them with code, or by visiting the Settings > Permalinks page.
tutorial
? – Sally CJ Commented Nov 28, 2018 at 3:33