WordPress.org

Make WordPress Core

Opened 3 years ago

Closed 8 months ago

Last modified 8 months ago

#16323 closed defect (bug) (fixed)

Hierarchical CPTs without a custom query_var 404

Reported by: jrcowher Owned by: duck_
Milestone: 3.7 Priority: normal
Severity: normal Version: 3.0.4
Component: Query Keywords: has-patch needs-testing
Focuses: Cc:

Description

When starting off with the post type set to non-hierarchical and then setting the hierarchical parameter in register_post_type() to true Wordpress will generate an invalid name query var (see attached files). If a generate a new rewrite rule in my functions file (e.g. service/(.*?)/(.*?)/?$' => 'index.php?post_type=service&name=$matches[2]) this appears to fix the problem. Removing the custom rewrite rule will cause the error to reappear.

Attachments (5)

Screen shot 2011-01-20 at 3.01.43 PM.png (171.0 KB) - added by jrcowher 3 years ago.
Screen shot 2011-01-20 at 3.06.06 PM.png (25.3 KB) - added by jrcowher 3 years ago.
16323.diff (1.3 KB) - added by duck_ 8 months ago.
16323.2.diff (1.9 KB) - added by wonderboymusic 8 months ago.
16323.hierarchical-rewrite-tag.diff (628 bytes) - added by duck_ 8 months ago.

Download all attachments as: .zip

Change History (16)

comment:1 follow-up: nacin3 years ago

Were rewrite rules flushed at any point?

comment:2 in reply to: ↑ 1 jrcowher3 years ago

Replying to nacin:

Were rewrite rules flushed at any point?

Yes, quite a few times via Settings -> Permalinks -> Save Changes

comment:3 follow-up: scribu3 years ago

Please paste the full code you're using to register the post type.

comment:4 in reply to: ↑ 3 jrcowher3 years ago

Replying to scribu:

Please paste the full code you're using to register the post type.

function post_type_service() {
	register_post_type(
		'service', array(
			'labels' => array(
		       'name' => 'Services',
		       'singular_name' => 'Service',
		       'add_new' => 'Add new',
		       'add_new_item' => 'Add new service',
		       'edit_item' => 'Edit service',
		       'search_items' => 'Search services',
		       'not_found' => 'No services found',
		       'not_found_in_trash' => 'No services found in trash',
		    ),
	    'menu_position' => 20,
		'public' => true,
		'show_ui' => true,
		'hierarchical' => true,
		'query_var' => false,
		'exclude_from_search' => false,
		'supports' => array(
			'title', 
			'editor',
			'page-attributes'
		)
    ));
 
	register_taxonomy( 
		'service-cats', 'service', array( 
			'hierarchical' => true, // Category or Tag functionality
			'labels' => array(
			     'name' => 'Categories',
			     'singular_name' => 'Category',
			     'search_items' => 'Search categories',
			     'popular_items' => 'Popular categories',
			     'all_items' => 'All categories',
			     'parent_item' => null,
			     'parent_item_colon' => null,
			     'edit_item' => 'Edit category',
			     'update_item' => 'Update category',
			     'add_new_item' => 'Add new category',
			     'new_item_name' => 'New category',
			     'separate_items_with_commas' => 'Separate categories with commas',
			     'add_or_remove_items' => 'Add or remove categories',
			     'choose_from_most_used' => 'Choose from most used categories'
			 )
		)
	);
}
add_action('init', 'post_type_service');

comment:5 c3mdigital8 months ago

  • Keywords needs-patch added

I can verify the reporters bug. Using the pasted code provided by the reporter I obtained the following results:

The name query_var is wrong.

Request:
service/treatments-therapeautic/diagnostics-bulger

Query String:
name=treatments-therapeautic%2Fdiagnostics-bulger&post_type=service

Matched Rewrite Rule:
service/(.+?)(/[0-9]+)?/?$

Matched Rewrite Query:
post_type=service&name=treatments-therapeautic%2Fdiagnostics-bulger&page=

In the var_dump of the query_vars 'name' => 'treatments-therapeauticdiagnostics-bulger

Adding this rewrite rule fixes the problem:
$rule['service/(.*?)/(.*?)/?$'] = 'index.php?post_type=service&name=$matches[2]';

After the new rule

Request:
service/treatments-therapeautic/diagnostics-bulger

Query String:
name=diagnostics-bulger&post_type=service

Matched Rewrite Rule:
service/(.*?)/(.*?)/?$

Matched Rewrite Query:
post_type=service&name=diagnostics-bulger

comment:6 duck_8 months ago

  • Component changed from Permalinks to Query
  • Summary changed from Hierarchical Custom Post Type Bug - invalid name query var generated to Hierarchical CPTs without a custom query_var 404

The problem here is that hierarchical post types that have been registered without a query_var will 404 when requesting child items. This occurs because the name query var is not mapped to pagename if the post type query_var doesn't exist. Simplified from WP_Query:

foreach ( (array)$q['post_type'] as $_post_type ) {
  $ptype_obj = get_post_type_object($_post_type);
  if ( !$ptype_obj || !$ptype_obj->query_var || empty($q[ $ptype_obj->query_var ]) )
    continue;

  if ( $ptype_obj->hierarchical && strpos($q[ $ptype_obj->query_var ], '/') !== false ) {                                                                                               
    $q['pagename'] = $q[ $ptype_obj->query_var ];
    $q['name'] = '';
  }
}

With pagename not set the path is not sent through get_page_by_path(), but directly queried as the post_name after sanitisation.

This code originates from [14072] for #12704.

duck_8 months ago

comment:7 duck_8 months ago

  • Keywords has-patch needs-testing added; needs-patch removed

16323.diff shoehorns in a mapping from 'name' to 'pagename'. If a cleaner approach could be found that would be good.

wonderboymusic8 months ago

comment:8 wonderboymusic8 months ago

  • Milestone changed from Awaiting Review to 3.7

changed the inline comment from postname to pagename

comment:9 duck_8 months ago

We can also fix the rewrite rules so that a hierarchical rewrite tag will use the pagename variable, see 16323.hierarchical-rewrite-tag.diff. The 'drawback' is that get_page_by_path() would be used for all queries (though this is the same behaviour as pages).

Also, I think that the mapping should be done as well anyway.

comment:10 duck_8 months ago

  • Owner set to duck_
  • Resolution set to fixed
  • Status changed from new to closed

In 25182:

Correct rewrite tag for hierarchical post types without a query_var.

Hierarchical rewrite rules operate via the 'pagename' query variable which is
passed to get_page_by_path(). However, the current rewrite rules use the 'name'
query variable for hierarchical types without a custom query_var.

Fixes #16323.

comment:11 duck_8 months ago

Discussed this with Dion in IRC. We decided that it would be best to fix the rewrite rules for this ticket and open a new one to improve the query variable mapping (see #25190).

Note: See TracTickets for help on using tickets.