I've created custom permalinks for various custom post types on a website. They all worked. Until recently I added another one, which I cannot get to work 8-o. The "company" struct is not working and gives a 404..

Can anyone spot a flaw in my thinking or put me on the right track? I must be forgetting something very stupid ;-)

Oh, I also went to the permalink settings page to flush the old permalinks / permalink cache / ...

Here's the code for the custom structure:

// rewrite rewrite
global $wp_rewrite;

$wp_rewrite->add_rewrite_tag("%merkname%", '([^/]+)', "merk=");
$wp_rewrite->add_permastruct('merk', '/merken/%merkname%', false);

$wp_rewrite->add_rewrite_tag("%modelname%", '([^/]+)', "model=");
$wp_rewrite->add_permastruct('model', '/merken/%merkname%/%modelname%', false);

$wp_rewrite->add_rewrite_tag("%carname%", '([^/]+)', "car=");
$wp_rewrite->add_permastruct('car', '/merken/%merkname%/%modelname%/%carname%', false);

$wp_rewrite->add_rewrite_tag("%companyname%", '([^/]+)', "company=");
$wp_rewrite->add_permastruct('company', '/company/%companyname%', false);

function kw_custom_permalink($permalink, $post, $leavename) {

    if ( '' != $permalink && !in_array($post->post_status, array('draft', 'pending', 'auto-draft')) ) {

        $merkname='';
        $modelname='';
        $carname='';
        $companyname='';

        if ( strpos($permalink, '%merkname%') !== false ) {
            $merkname = $post->post_name;
        }

        if ( strpos($permalink, '%modelname%') !== false ) {
            $merkpost = get_post( get_post_meta( $post->ID, "merk", true ) );
            $merkname = $merkpost->post_name;
            $modelname = $post->post_name;
        }

        if ( strpos($permalink, '%carname%') !== false ) {
            $merkpost = get_post( get_post_meta( $post->ID, "_car_merk", true ) );
            $merkname = $merkpost->post_name;

            $modelpost = get_post( get_post_meta( $post->ID, "_car_model", true ) );
            $modelname = $modelpost->post_name;

            $carname = $post->post_name;
        }

        if ( strpos($permalink, '%companyname%') !== false ) {
            $companyname = $post->post_name;
        }

        $permalink = str_replace(
            array(
                $leavename? '' : '%postname%',
                '%post_id%',
                '%merkname%',
                '%modelname%',
                '%carname%',
                '%companyname%',
                $leavename? '' : '%pagename%',
            ), 
            array(
                $post->post_name,
                $post->ID,
                $merkname,
                $modelname,
                $carname,
                $companyname,
                $post->post_name,
            ), 
            $permalink
            );

    }
    return $permalink;
}
add_filter('post_type_link', 'kw_custom_permalink', 10, 3);
  • You shouldn't add your permastructs etc in the global namespace, you should hook into the appropriate place then modify $wp_rewrite as ordering can matter. Also have you tried flushing permalinks? – Tom J Nowell Dec 3 '14 at 11:48
  • Flushing I tried. What would be the appropriate hook for adding permastructs? "init"? – JosFabre Dec 5 '14 at 8:31

You're currently placing your rewrite rules in the global scope, which means they execute as soon as your file is loaded, which may be too early. Instead try adding them on the init hook, or rewriting them to use the generate_rewrite_rules filter instead, e.g.:

add_action('generate_rewrite_rules', 'themes_dir_add_rewrites');

function themes_dir_add_rewrites() {
  $theme_name = next(explode('/themes/', get_stylesheet_directory()));

  global $wp_rewrite;
  $new_non_wp_rules = array(
    'css/(.*)'       => 'wp-content/themes/'. $theme_name . '/css/$1',
    'js/(.*)'        => 'wp-content/themes/'. $theme_name . '/js/$1',
    'images/wordpress-urls-rewrite/(.*)'    => 'wp-content/themes/'. $theme_name . '/images/wordpress-urls-rewrite/$1',
  );
  $wp_rewrite->non_wp_rules += $new_non_wp_rules;
}

Taken from Hongkiat

Or

function josfaber_add_rules() {
    global $wp_rewrite;

    $wp_rewrite->add_rewrite_tag("%merkname%", '([^/]+)', "merk=");
    $wp_rewrite->add_permastruct('merk', '/merken/%merkname%', false);

    $wp_rewrite->add_rewrite_tag("%modelname%", '([^/]+)', "model=");
    $wp_rewrite->add_permastruct('model', '/merken/%merkname%/%modelname%', false);

    $wp_rewrite->add_rewrite_tag("%carname%", '([^/]+)', "car=");
    $wp_rewrite->add_permastruct('car', '/merken/%merkname%/%modelname%/%carname%', false);

    $wp_rewrite->add_rewrite_tag("%companyname%", '([^/]+)', "company=");
    $wp_rewrite->add_permastruct('company', '/company/%companyname%', false);
}
add_action( 'init', 'josfaber_add_rules' );
  • It didn't solve the problem. But I see now this is the correct way to do this, so thank you for this one! – JosFabre Dec 9 '14 at 8:44
  • Wow, I thought I'd tried a different slug, but I did not change the post type name. I now tried with a fresh custom post type 'Business' and that works correctly. Anyone knows if 'company' might be a reserved slug? Or to prevent future issues, is there a list of reserved slugs to be found somewhere? – JosFabre Jan 8 '15 at 11:42
  • Company isn't reserved but that question would be interesting and I'm sure it's been asked and answered already – Tom J Nowell Jan 8 '15 at 12:33

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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