Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I have a custom post type whose permalink needs to sit in the same space as pages, like so:

/an-example-thing  <--  custom post type 'thing'
/about-the-things  <--  a normal page

I'm well aware that this isn't the recommended way to do it, but I don't really have a choice - that's what the client has specified.

I've created the custom types with register_post_type, and used the Custom Post Permalinks plugin to set their permalink like so:

/%thing%/

However, this creates a conflict between the rule that recognises my custom posts, and the one for normal pages - which turns all normal pages into 404s. This problem disappears when the permalink is changed to something like this:

/things/%thing%/

Using the Monkeyman Rewrite Analyser shows that the rule for the custom post is coming first. Even when I try forcing it to use verbose rules:

global $wp_rewrite;
$wp_rewrite->use_verbose_page_rules = true;

the custom post type rule is higher priority than the verbose rules for pages so they still get a 404.

I'd like it to look for things first, and when none is found with that name look for pages. The other way round would be acceptable. Is there no way of persuading it to look for both things and pages before hitting a 404?

share|improve this question
add comment

3 Answers

up vote 2 down vote accepted

You start with one bonus point for using my rewrite analyzer :-)

Indeed, even if you use verbose page rules, since version 3.1 (or something around that) the taxonomy rewrite rules come even before that. I recently answered another question with a way to move them really to the top. This should work if you don't mind having verbose page rules (if you don't have more than 25 pages or so).

If you don't want verbose page rules you will have to extend the core WP class so it can deal with "ambiguous" situations where the URL can refer to a page or a custom post type. Mike once provided a nice way to do this. His answer is written for a custom taxonomy, but it should be adaptable to a custom post type too.

share|improve this answer
    
So he replaces the entire wordpress object in order to catch one route? Wow... :) –  Marcus Downing May 18 '11 at 12:50
    
@Marcus: There is currently no better way to extend the routing mechanism. And the entire WP object is not that much - most of WordPress is not in classes, the WP class only does (very simple) routing. –  Jan Fabry May 18 '11 at 12:53
    
I haven't done this yet, but it looks like the correct answer so I'm accepting it. –  Marcus Downing May 19 '11 at 8:44
    
The WP 3.3 proudly advertises: "Use the postname permalink structure without a performance penalty", but does not mention can we use it with custom post types? And especially how to do so? –  Ciantic Jan 1 '12 at 9:07
add comment

There are two plugin that address this problem.

This one removes the type slug by adding a specific rule for each custom post type page.

This one seems more advanced, it lets you set up any slug structure you want, but it also is abandoned by the developer.

I got both of them to work, although initially I had to debug with Monkeyman Rewrite Analyzer because some other rules were interfering.

share|improve this answer
add comment

I found one solution, but it's really ugly: hook into 404 routing to deliver the page that should be delivered. The code is bit complicated because I have a multisite prefix to deal with as well.

theme/404.php

<?php
global $current_blog;
$prefix = $current_blog->path;
$path = $_SERVER['REQUEST_URI'];
$path = preg_replace("!^$prefix!i", "", $path);
$path = preg_replace("!\?.*$!i", "", $path);
$path = trim($path, '/');
$page = get_page_by_path($path);

if (isset($page)) {
  $template = get_post_meta($page->ID, '_wp_page_template', true);
  if (empty($template))
    $template = get_page_template();
  query_posts("post_type=page&id={$page->ID}");
  include($template);
  die;
}
?>
...actually handle a 404...

Having identified a page, it has to run query_posts again to load all the data correctly. This is far from the ideal solution, but it at least worked for me. I'd gladly replace it with a better solution if anyone can suggest one.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.