Forums

Custom Post Type - redirect problem (3 posts)

  1. loushou
    Member
    Posted 1 year ago #

    Working with 'custom post types', I ran into a snag. It did not seem to be as plug-and-play as it has been depicted on many many articles. Consider the following for WP3.0:

    function bmrw_init() {
      register_post_type('my_custom_pt', array(
        'label' => 'My Custom Post Types',
        'singular_label' => 'My Custom Post Type',
        'description' => 'A new post type.',
        'public' => true,
        'show_ui' => true,
        '_builtin' => false,
        'query_var' => false,
        'rewrite' => array( 'slug' => 'my_custom_pt',),
        'capability_type' => 'post',
        'hierarchial' => false,
        'supports' => array('title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments', 'custom-fields', 'revisions'),
      ));
    }
    add_action('init', 'bmrw_init');

    So according to many articles similar to this one, the above should produce permalinks like this:

    http://www.my-site.com/my_custom_pt/testing-post/

    And also according to those articles, when going to that url, the post should come up all honky-dory. The problem I ran into was that the permalink was getting constructed properly, but when I browsed to the url, I was getting a 404 error.

    Like I always do, I started doing some debugging and searching to narrow down the problem. After about 5 hours I found the following.

    Looking in wp-includes/classes.php, on line 146, I saw the following code:

    $rewrite = $wp_rewrite->wp_rewrite_rules();

    This code gets a list of all the search and replace values for custom post types, such that, in theory, a url like this:

    http://www.my-site.com/my_custom_pt/testing-post/

    should be translated to:

    http://www.my-site.com/index.php?post_type=my_custom_pt&name=testing-post&page=1

    The problem was, that the translated url was coming out as:

    http://www.my-site.com/index.php?post_type=my_custom_pt&name=$1&page=$2

    So the rules were not being written properly, in my case. I thought maybe that I just did not have the latest version of WP3.0, so I re-downloaded it, and compared the code. It was identical. So I looked into it a bit further, to find out why these $1 and $2 was not getting replaced.

    A bit below the code that retrieves the rules, I found where the replacement should take place:

    foreach ( (array) $rewrite as $match => $query) {
    				// Don't try to match against AtomPub calls
    				if ( $req_uri == 'wp-app.php' )
    					break;
    
    				// If the requesting file is the anchor of the match, prepend it
    				// to the path info.
    				if ( (! empty($req_uri)) && (strpos($match, $req_uri) === 0) && ($req_uri != $request) )
    					$request_match = $req_uri . '/' . $request;
    
    				if ( preg_match("#^$match#", $request_match, $matches) ||
    					preg_match("#^$match#", urldecode($request_match), $matches) ) {
    					// Got a match.
    					$this->matched_rule = $match;
    
    					// Trim the query of everything up to the '?'.
    					$query = preg_replace("!^.+\?!", '', $query);
    
    					// Substitute the substring matches into the query.
    					$query = addslashes(WP_MatchesMapRegex::apply($query, $matches));
    
    					$this->matched_query = $query;
    
    					// Parse the query.
    					parse_str($query, $perma_query_vars);
    
    					// If we're processing a 404 request, clear the error var
    					// since we found something.
    					if ( isset($_GET['error']) )
    						unset($_GET['error']);
    
    					if ( isset($error) )
    						unset($error);
    
    					break;
    				}
    			}

    Now most of this code is not really that suspicious; however, there is one piece of code that is:

    WP_MatchesMapRegex::apply($query, $matches)

    This code basically uses the the following regular expression to replace the search values in the parsed url:

    // this is not the actual code, just a representation of it
    $parsed_url = 'http://www.my-site.com/index.php?post_type=my_custom_pt&name=$1&page=$2';
    
    // this is the actual regular expression
    $regular_expression = '(\$matches\[[1-9]+[0-9]*\])';

    So basically the replacement utility used to put the values in place of the placeholders is looking for:

    '...$matches[1]..'

    and our string has:

    '...$1...'

    There is the problem. So I decided to find what was creating the $1 and $2, because they obviously need to be $matches[1] and $matches[2], in order to actually be replaced.

    I searched through the rewrite.php file (the file that produces the rules), and I found that the following function created the $1 and $2:

    function preg_index($number) {
    		$match_prefix = '$';
    		$match_suffix = '';
    
    		if ( ! empty($this->matches) ) {
    			$match_prefix = '$' . $this->matches . '[';
    			$match_suffix = ']';
    		}
    
    		return "$match_prefix$number$match_suffix";
    	}

    I determined that because $wp_rewrite->matches was set to '' (nothing), that this function was only putting placeholders like $1 and $2, instead of the proper working version of $matches[1] and $matches[2].

    So I came up with a hot-fix for the problem in my 'custom post type' creation function:

    function bmrw_init() {
      /** new lines for hot-fix start */
      global $wp_rewrite;
    
      $wp_rewrite->matches = 'matches';
      /** new lines for hot-fix end */
    
      register_post_type('minisite', array(
        'label' => 'Mini-Sites',
        'singular_label' => 'Mini-Site',
        'description' => 'A miniture site about a specific topic inside the main site.',
        'public' => true,
        'show_ui' => true,
        '_builtin' => false,
        'query_var' => false,
        'rewrite' => array( 'slug' => 'topics',),
        'capability_type' => 'post',
        'hierarchial' => false,
        'supports' => array('title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments', 'custom-fields', 'revisions'),
      ));
    }
    add_action('init', 'bmrw_init');

    The lines I added, solved the problem. But I don't think that this is a permanent solution to the problem. The only real place that the rewrite engine rewrite.php is called (on a site that has a proper .htaccess file) is in classes.php, on the lines I have pasted here. My long term solution to this problem is to set the default value of $wp_rewrite->matches to 'matches', because the regular expressions replacement tool is the only interpreter of the rewrite rules, and it expects $matches[n].

    All this being said, I wonder how I can actually submit that as a bug, or if I completely missed something. If the later is the reason, please tell me what I am doing wrong.

    Thanks,
    Lou

  2. loushou
    Member
    Posted 1 year ago #

    Well, unfortunately, I still have not come up with any solutions for this on my own, nor through searching the internet for similar problems. So any expertise in this area at all, would be much appreciated.

  3. robkaq2
    Member
    Posted 1 year ago #

    Hi,

    In fact the solution is very easy.

    After registering you post type:

    register_post_type('robka_classified',$args);
    
    flush_rewrite_rules();

    flush_rewrite_rules will do it for you!

Topic Closed

This topic has been closed to new replies.

About this Topic