Ask your WordPress questions! Pay money and get answers fast! Comodo Trusted Site Seal
Official PayPal Seal

Custom taxonomy in URL, however pages now return 404 WordPress

I have created a custom post type called "articles", with a taxonomy called "article category". I used [[LINK href="http://stackoverflow.com/questions/23698827/custom-permalink-structure-custom-post-type-custom-taxonomy-post-name"]]this[[/LINK]] post to handle the permalinks, however my regular links return a 404. It would be nice in the editor to have the article_category not show up as "%article_category%" but this is not a huge concern.

Example

http://domain.com/articlecategory/article
http://web.com/animals/article

However,

http://domain.com/page
http://domain.com/about

returns a 404.

Here is my current code:


function article_init() {
$args = array(
'label' => 'Articles',
'public' => true,
'show_ui' => true,
'capability_type' => 'post',
'hierarchical' => true,
'menu_position' => 5,
'has_archive' => true,
'rewrite' => array('slug' => '%article_category%', 'with_front' => true),
'with_front' => true,
'query_var' => true,
'menu_icon' => 'dashicons-format-quote',
'supports' => array(
// 'title',
// 'editor',
// 'custom-fields'
)
);
register_post_type( 'article', $args );
}

add_action( 'init', 'article_init' );

function articleCategory_init() {
$labels = array(
'name' => _x( 'Article Categories', 'taxonomy general name' ),
'singular_name' => _x( 'Article Category', 'taxonomy singular name' ),
'search_items' => __( 'Search Article Categories' ),
'all_items' => __( 'All Article Categories' ),
'parent_item' => __( 'Parent Article Category' ),
'parent_item_colon' => __( 'Parent Article Category:' ),
'edit_item' => __( 'Edit Article Category' ),
'update_item' => __( 'Update Article Category' ),
'add_new_item' => __( 'Add New Article Category' ),
'new_item_name' => __( 'New Article Category' ),
'menu_name' => __( 'Article Categories' ),
);
$args = array(
'labels' => $labels,
'hierarchical' => true,
'show_ui' => true,
'query_var' => true,
'rewrite' => array('slug' => 'articles', 'with_front' => true),
);
register_taxonomy( 'article_category', 'article', $args );
}

add_action( 'init', 'articleCategory_init', 0 );





/**
* Tell WordPress how to interpret our project URL structure
*
* @param array $rules Existing rewrite rules
* @return array
*/
function so23698827_add_rewrite_rules( $rules ) {
$new = array();
$new['article/([^/]+)/(.+)/?$'] = 'index.php?article=$matches[2]';
$new['article/(.+)/?$'] = 'index.php?article_category=$matches[1]';

return array_merge( $new, $rules ); // Ensure our rules come first
}
add_filter( 'rewrite_rules_array', 'so23698827_add_rewrite_rules' );

/**
* Handle the '%project_category%' URL placeholder
*
* @param str $link The link to the post
* @param WP_Post object $post The post object
* @return str
*/
function so23698827_filter_post_type_link( $link, $post ) {
if ( $post->post_type == 'article' ) {
if ( $cats = get_the_terms( $post->ID, 'article_category' ) ) {
$link = str_replace( '%article_category%', current( $cats )->slug, $link );
}
}
return $link;
}
add_filter( 'post_type_link', 'so23698827_filter_post_type_link', 10, 2 );

Answers (4)

2015-07-26

Andrea P answers:

before I try to dive into it, could you please try to flush the permalinks rules?

go to Settings>Permalink and:
ensure that you are using pretty-permalinks (like "post name" option)
then change to something else
click to save
change back to "post name" or whatever is your choice.
click save
just to be sure, click save again. ;)

in my experience, 80% of the times when tweaking the permalink structure by using custom functions, what you need is to refresh them. and saving the permalinks options page, is forcing a complete refresh.


Delicious comments:

I have flushed them, yes but I have also changed from post name, to numeric and back to post name as you suggested. However it seems to have no impact as you can see from below.

https://www.dropbox.com/s/e83gx7k6cwpz9du/Screenshot%202015-07-26%2014.42.07.png

https://www.dropbox.com/s/xfudquhpoautthj/Screenshot%202015-07-26%2014.45.06.png

2015-07-26

Hariprasad Vijayan answers:

Hi,

Try this

function article_init() {
$args = array(
'label' => 'Articles',
'public' => true,
'show_ui' => true,
'capability_type' => 'post',
'hierarchical' => true,
'menu_position' => 5,
'has_archive' => true,
'rewrite' => array('slug' => 'article/%article_category%','with_front' => true),
'with_front' => true,
'query_var' => true,
'menu_icon' => 'dashicons-format-quote',
'supports' => array(
// 'title',
// 'editor',
// 'custom-fields'
)
);
register_post_type( 'article', $args );
}
add_action( 'init', 'article_init' );
function articleCategory_init() {
$labels = array(
'name' => _x( 'Article Categories', 'taxonomy general name' ),
'singular_name' => _x( 'Article Category', 'taxonomy singular name' ),
'search_items' => __( 'Search Article Categories' ),
'all_items' => __( 'All Article Categories' ),
'parent_item' => __( 'Parent Article Category' ),
'parent_item_colon' => __( 'Parent Article Category:' ),
'edit_item' => __( 'Edit Article Category' ),
'update_item' => __( 'Update Article Category' ),
'add_new_item' => __( 'Add New Article Category' ),
'new_item_name' => __( 'New Article Category' ),
'menu_name' => __( 'Article Categories' ),
);
$args = array(
'labels' => $labels,
'hierarchical' => true,
'show_ui' => true,
'query_var' => true,
'rewrite' => array('slug' => 'articles', 'with_front' => true),
);
register_taxonomy( 'article_category', 'article', $args );
}

add_action( 'init', 'articleCategory_init', 0 );
/**
* Tell WordPress how to interpret our article URL structure
*
* @param array $rules Existing rewrite rules
* @return array
*/
function so23698827_add_rewrite_rules( $rules ) {
$new = array();
$new['article/([^/]+)/(.+)/?$'] = 'index.php?article=$matches[2]';
$new['article/(.+)/?$'] = 'index.php?article_category=$matches[1]';

return array_merge( $new, $rules ); // Ensure our rules come first
}
add_filter( 'rewrite_rules_array', 'so23698827_add_rewrite_rules' );

/**
* Handle the '%article_category%' URL placeholder
*
* @param str $link The link to the post
* @param WP_Post object $post The post object
* @return str
*/
function so23698827_filter_post_type_link( $link, $post ) {
if ( $post->post_type == 'article' ) {
if ( $cats = get_the_terms( $post->ID, 'article_category' ) ) {
$link = str_replace( '%article_category%', current( $cats )->slug, $link );
}
}
return $link;
}
add_filter( 'post_type_link', 'so23698827_filter_post_type_link', 10, 2 );


Delicious comments:

This seems to work fine! Thanks. I am not sure how to award the prize, however.


Delicious comments:

This seems to work fine! Thanks. I am not sure how to award the prize, however.


Delicious comments:

Oops, just noticed that I wanted to have the "article" part removed.

2015-07-27

IndiTheme - answers:

try this....


function article_init() {
/**
* Register custom Article post type.
*
*/
$labels = array(
'name' => __( 'Articles', 'textdomain' ),
'singular_name' => __( 'Article', 'textdomain' ),
'menu_name' => __( 'Articles', 'textdomain' ),
'name_admin_bar' => __( 'Article', 'textdomain' ),
'add_new' => __( 'Add New', 'textdomain' ),
'add_new_item' => __( 'Add New Article', 'textdomain' ),
'new_item' => __( 'New Article', 'textdomain' ),
'edit_item' => __( 'Edit Article', 'textdomain' ),
'view_item' => __( 'View Article', 'textdomain' ),
'all_items' => __( 'All Articles', 'textdomain' ),
'search_items' => __( 'Search Articles', 'textdomain' ),
'parent_item_colon' => __( 'Parent Articles:', 'textdomain' ),
'not_found' => __( 'No Articles found.', 'textdomain' ),
'not_found_in_trash' => __( 'No Articles found in Trash.', 'textdomain' )
);

$args = array(
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'article' ),
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => true, /* set to false */
'menu_position' => 5,
'supports' => array()
);

register_post_type( 'article', $args );

}

add_action( 'init', 'article_init' );

function articleCategory_init() {
/**
* Register a article_category taxonomy.
*
*/

$labels = array(
'name' => __( 'Article Categories', 'textdomain' ),
'singular_name' => __( 'Article Category', 'textdomain' ),
'search_items' => __( 'Search Article Categories', 'textdomain' ),
'all_items' => __( 'All Article Categories', 'textdomain' ),
'parent_item' => __( 'Parent Article Category', 'textdomain' ),
'parent_item_colon' => __( 'Parent Article Category', 'textdomain' ) . ':',
'edit_item' => __( 'Edit Article Category', 'textdomain' ),
'update_item' => __( 'Update Article Category', 'textdomain' ),
'add_new_item' => __( 'Add New Article Category', 'textdomain' ),
'new_item_name' => __( 'New Article Category Name', 'textdomain' ),
'menu_name' => __( 'Article Category', 'textdomain' ),
);

$args = array(
'hierarchical' => true,
'labels' => $labels,
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'article_category' ),
);

register_taxonomy( 'article_category', array( 'article' ), $args );

}

add_action( 'init', 'articleCategory_init', 0 );

/**
* Tell WordPress how to interpret our project URL structure
*
* @param array $rules Existing rewrite rules
* @return array
*/

function so23698827_add_rewrite_rules( $rules ) {
$new = array();
$new['article/([^/]+)/(.+)/?$'] = 'index.php?article=$matches[2]';
$new['article/(.+)/?$'] = 'index.php?article_category=$matches[1]';
return array_merge( $new, $rules ); // Ensure our rules come first

}
add_filter( 'rewrite_rules_array', 'so23698827_add_rewrite_rules' );

/**
* Handle the '%project_category%' URL placeholder
*
* @param str $link The link to the post
* @param WP_Post object $post The post object
* @return str
*/

function so23698827_filter_post_type_link( $link, $post ) {
if ( $post->post_type == 'article' ) {
if ( $cats = get_the_terms( $post->ID, 'article_category' ) ) {
$link = str_replace( '%article_category%', current( $cats )->slug, $link );
}
}
return $link;
}
add_filter( 'post_type_link', 'so23698827_filter_post_type_link', 10, 2 );


After you insert the code, <strong>re-save</strong> your custom permalink...

Take look on my dev web.... it's works....

2015-07-29

Dbranes answers:

The rewrite rules can be hard to work with.

We should e.g. note the "Black magic" warning in the WordPress core, regarding the rewrite rules ;-)

I'm not joking, it says:

<blockquote> * The main WP_Rewrite function for building the rewrite rule list. The
* contents of the function is a mix of black magic and regular expressions,
* so best just ignore the contents and move to the parameters.
</blockquote>

and then after the "black magic" it reads:

<blockquote> //the finished rules. phew!
</blockquote>



<strong> THE PROBLEM:</strong>


The %article_category% part is replaced with ([^/]+) when the rewrite rules are generated.

/([^/]+)/...etc...

and since you don't got any base slug identifier, it will clash with the rewrite rules for pages:

/(.?.+?)/...etc...

So to solve this, the recommended way is to add the extra base slug, e.g. as @Hariprasad did with:

'rewrite' => array('slug' => 'article/%article_category%','with_front' => true),

to avoid clashes.

There are few workarounds if you don't want that recommended extra base:

<strong> WORKAROUND - with underscore</strong>

Note that register_taxonomy() will automatically add the taxonomy slug as rewrite tag.

So let's use %artcat% instead of %article_category%. Then we can

add_rewrite_tag( '%artcat%','(_[^/&]+)' );

We could also override the '([^/]+)' part of %article_category% by calling:

add_rewrite_tag( '%article_category%','(_[^/&]+)' );

after register_taxonomy() as been called.

Then we might use these combinations together:

example.tld/_animals/article/

and

example.tld/mypage

We might also use different prefixes: ac_, ac, artcat, ... instead of the underscore.


<strong> WORKAROUND - without underscore </strong>

It's possible to use these combinations together:

example.tld/animals/article/

and

example.tld/mypage

by intercepting the process when the url is changed into query variables, with extra database query(ies).

<em>ps: If you're interested in this approach you can PM me.</em>