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.

Is it possible for a custom post type to have a permalink as domain.com/custom-slug/ instead of domain.com/custom/custom-slug/?

I can't seem to achieve it. rewrite argument while registering it either defaults to the latter one or a custom one by using 'rewrite' => array( 'slug' => 'blah-blah' )

share|improve this question
    
by "custom-slug" you mean the post's slug? –  Bainternet Mar 1 '11 at 10:56
    
@Bainternet exactly, I want it to be like how a WP page is –  Ashfame Mar 1 '11 at 10:58
    
@Ashfame, were you able to get this figured out? I'm trying to accomplish the same myself now. –  Jonathan Wold Jan 22 '12 at 20:30
add comment

2 Answers

To completely remove the slug so that the URL structure would look like:

http://domain.com/post-slug/

in your register_post_type set

'rewrite' => array('slug' => false, 'with_front' => false)

hope this helps

share|improve this answer
    
Didn't work for me, does it work for you? I mean have you tested it, that it works? –  Ashfame Mar 1 '11 at 12:02
    
Yes it works if your permalink structure is/%postname%/ –  Bainternet Mar 1 '11 at 13:44
    
Sorry didn't work for me in a fresh 3.1 install –  Ashfame Mar 1 '11 at 17:29
    
I can confirm that this does not work. –  Mike Feb 1 '12 at 18:41
add comment

Hi @Ashfame:

Take a look at my answer to the following question. You can modify my parse_request() to get what you need:

And you can read the following to see why what you want can cause issues in WordPress and requires a complex solution:

UPDATE

Based on the comment I decided to go ahead and implement this as the next revision of the plugin. It's really only tested for the use-case for this question and the one from the prior referenced question. Over time I plan to implement it for all potential use-cases, as questions or clients occur to drive the demand.

Here is the code you'd place in your theme's functions.php file to set it up for the post_type 'custom':

add_action('init','init_url_routes');
function init_url_routes() {
  $post_type = 'custom'; // Change this to your actual post_type name
  register_url_route(array('post_type'=>$post_type));
}

And here is the plugin which you can place in /wp-content/mu-plugins/:

<?php
/*
Filename: wp-extended.php
Plugin Name: WP Extended for Taxonomy URL Routes
Author: Mike Schinkel
Version: 0.2
*/
function register_url_route($args=array()) {
  WP_Extended::register_url_route($args);
}
class WP_Extended extends WP {
  static $root = array();
  static function on_load() {
    add_action('setup_theme',array(__CLASS__,'setup_theme'));
  }
  static function register_url_route($args) {
    if (isset($args['taxonomy']))
      self::$root['taxonomy'][$args['taxonomy']] = get_taxonomy($args['taxonomy']);
    if (isset($args['post_type']))
      self::$root['posts'][$args['post_type']] = get_post_type_object($args['post_type']);
  }
  static function setup_theme() { // Setup theme is 1st code run after WP is created.
    global $wp;
    $wp = new WP_Extended();  // Replace the global $wp
  }
  function parse_request($extra_query_vars = '') {
    $path = $_SERVER['REQUEST_URI'];
    $domain = str_replace('.','\.',$_SERVER['SERVER_NAME']);
    $root_path = preg_replace("#^https?://{$domain}(/.*)$#",'$1',WP_SITEURL);
    if (substr($path,0,strlen($root_path))==$root_path)
      $path = substr($path,strlen($root_path));
    list($path) = explode('?',$path);
    $path_segments = explode('/',trim($path,'/'));
    // This does not handle ordering priority of type to match yet
    $matched = $this->parse_post_type_request($path_segments);
    if (!$matched)
      $matched = $this->parse_taxonomy_request($path_segments);
    if ($matched) {
      // This is hamfisted but necessary in some cases.
      // TODO: Look into ways to have more finesse with this.
      remove_action('template_redirect','redirect_canonical');
    } else {
      parent::parse_request($extra_query_vars); // Delegate to WP class
    }
  }
  function parse_post_type_request($path_segments) {
    // This does not handle heirarchical pages yet
    $post_id = false;
    global $wpdb;
    $sql =<<<SQL
SELECT
  ID
FROM
  {$wpdb->posts}
WHERE 1=1
  AND post_status='publish'
  AND post_type='%s'
  AND post_name='%s'
SQL;
    if (is_array(self::$root['posts'])) {
      foreach(self::$root['posts'] as $post_type => $post_type_object) {
        $sql = $wpdb->prepare($sql,$post_type,$path_segments[0]);
        $post_id = $wpdb->get_var($sql);
        if ($post_id) {
          $this->query_vars[($post_type=='page' ? 'page_id' : 'p')] = $post_id;
          unset($path_segments[0]);  // Remove from future consideration
          break;
        }
      }
    }
    return ($post_id);
  }
  function parse_taxonomy_request($path_segments) {
    $taxonomy_term = array();
    $parent_id = 0;
    if (is_array(self::$root['taxonomy'])) {
      foreach(self::$root['taxonomy'] as $taxonomy_slug => $taxonomy) {
        $terms = get_terms($taxonomy_slug);
        foreach($path_segments as $segment_index => $path_segment) {
          foreach($terms as $term_index => $term) {
            if ($term->slug==$path_segment) {
              if ($term->parent!=$parent_id) { // Make sure we test parents
                $taxonomy_term = array();
              } else {
                $parent_id = $term->term_id; // Capture parent ID for verification
                $taxonomy_term[] = $term->slug; // Collect slug as path segment
                unset($terms[$term_index]); // No need to scan it again
              }
              unset($path_segments[$segment_index]);  // Remove from future consideration
              break;
            }
          }
        }
        if (count($taxonomy_term))
          break;
      }
      if (count($taxonomy_term)) {
        $path = implode('/',$taxonomy_term);
        switch ($taxonomy_slug) {
          case 'category':
            $this->query_vars['category_name'] = $path;
            break;
          case 'post_tag':
            $this->query_vars['tag'] = $path;
            break;
          default:
            $this->query_vars['taxonomy'] = $taxonomy_slug;
            $this->query_vars['term'] = $path;
            break;
        }
      }
    }
    return count($taxonomy_term);
  }
}
WP_Extended::on_load();
share|improve this answer
    
Hi @Mike I am aware of the permalinks performance issue. For this particular project, the site won't exceed 20 pages, so its totally acceptable for me. And regarding your first link, it totally went way over my head. I will try reading it again. Thanks for the great answers! :) –  Ashfame Mar 1 '11 at 17:29
    
@Ashframe - Try the code in your test site and see how it enables categories in the root. That might inform your understanding? As for the performance issue, I usually answer as much for future readers who may not know about something as I do for the OP (you in this case.) –  MikeSchinkel Mar 1 '11 at 17:40
    
@Ashframe - I added code for you to try. –  MikeSchinkel Mar 1 '11 at 18:54
    
@MikeSchinkel - I'm attempting to use this code for the same use-case. I'm not quite getting it.. How can this be used to strip out the post type slug from the permalink? –  Jonathan Wold Jan 22 '12 at 20:33
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.