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

Custom Post Types and Permalinks in Gridnik Theme WordPress

  • SOLVED

This is for a new site just about to launch using:
- WP 3.1
- purchased Gridnik Theme 1.2.3 (latest) @ http://themeforest.net/item/gridnik-elite-portfolio-wordpress-theme/145673
- This theme uses WizyPanel
- Hosted with Dreamhost.

I'm fairly good with PHP, but don't know all the details on how WP handles the new register_post_type and how that effect URL rewrites.

<strong>Here is what I want:</strong>
URL = domain.com/POST-NAME-SLUG

Right now it is:
URL = domain.com/project/POST-NAME-SLUG

My Permalinks have been set to:
Custom Structure - /%postname%
ie. domain.com/post-slug-here
I use this setting for most of my sites just fine.


On my own I've traced down where register_post_type is setup within the Theme files and it's settings. Here is that code/php file.
<?php

add_action('init', 'wizy_create_portfolio');
add_action('init', 'register_projects_cats');
add_action('init', 'register_projects_tags');

// creates portfolio > projects post type
function wizy_create_portfolio() {
register_post_type(
'project',
array(
'labels' => array(
'name' => __('Projects'),
'singular_name' => __('Project'),
'add_new' => __('New Project'),
'add_new_item' => __('Add New Project'),
'edit' => __('Edit'),
'edit_item' => __('Edit Project'),
'new_item' => __('New Project'),
'view' => __('View Project'),
'view_item' => __('View Project'),
'search_items' => __('Search Projects'),
'not_found' => __('No projects found'),
'not_found_in_trash' => __('No projects found in Trash')
),
'public' => true,
'show_ui' => true,
'publicly_queryable' => true,
'exclude_from_search' => false,
'supports' => array('title', 'editor', 'thumbnail', 'comments', 'page-attributes', 'author'),
'menu_icon' => WIZYP_URI . '/images/projects.png',
'menu_position' => 5,
// 'rewrite' => false
'rewrite' => array('slug' => 'brilliant') // makes .com/brilliant/%postname%
)
);
} // end wizy_create_portfolio

function register_projects_cats() {
register_taxonomy(
'projects-category',
array('project'),
array(
'public' => true,
'labels' => array(
'name' => __( 'Projects\' Categories' ),
'singular_name' => __( 'Projects\' Category' ),
'search_items' => __( 'Search Projects\' Categories' ),
'popular_items' => __( 'Popular Projects\' Categories' ),
'all_items' => __( 'All Projects\' Categories' ),
'parent_item' => __( 'Parent Projects\' Category' ),
'parent_item_colon' => __( 'Parent Projects\' Category:' ),
'edit_item' => __( 'Edit Projects\' Category' ),
'update_item' => __( 'Update Projects\' Category' ),
'add_new_item' => __( 'Add New Projects\' Category' ),
'new_item_name' => __( 'New Projects\' Category Name' ),
),
'hierarchical' => true
)
);
} // end register_projects_cats

function register_projects_tags() {
register_taxonomy(
'projects-tags',
array('project'),
array(
'public' => true,
'labels' => array(
'name' => __( 'Projects\' Tags' ),
'singular_name' => __( 'Projects\' Tag' ),
'search_items' => __( 'Search Projects\' Tags' ),
'popular_items' => __( 'Popular Projects\' Tags' ),
'all_items' => __( 'All Projects\' Tags' ),
'parent_item' => __( 'Parent Projects\' Tag' ),
'parent_item_colon' => __( 'Parent Projects\' Tag:' ),
'edit_item' => __( 'Edit Projects\' Tag' ),
'update_item' => __( 'Update Projects\' Tag' ),
'add_new_item' => __( 'Add New Projects\' Tag' ),
'new_item_name' => __( 'New Projects\' Tag Name' ),
),
'hierarchical' => false
)
);
} // end register_projects_tags

?>

Above is the file extension.custom-post-types.php in the extensions folder of theme.


At the end of register_post_type you can see I added a line for rewrite.
I tried rewrite = false but that just made the URLs do this: domain.com/?project=post-name-slug


I tried this line of code too:
'rewrite' => array('slug'=>'','with_front'=>false),
This resulted in domain.com/project/post-name-slug as well.


I also just made WP replace projects with something else with this line:
'rewrite' => array('slug' => 'brilliant')
This works, but just changes project to brilliant. ie. domain.com/brilliant/post-name-slug
But that's not exactly what I want. :(

Each time I change something I make sure to go to Permalinks and re-save to that the rules get flushed. But still no dice. Is there something else I need to do?

Now this is where I get stuck.

<strong>How can I achieve the proper URL structure I want while adhering to this custom post type within the theme?</strong>

The author of the theme and wizypanel seems to be overwhelmed right now. I see a few people in the comments on ThemeForest (link above) asking for this same thing, but he hasn't built it in yet.

Who wants to figure this one out?

Here is the WP Function Reference: http://codex.wordpress.org/Function_Reference/register_post_type

Answers (3)

2011-05-02

AdamGold answers:

Try to set your rewrite like this:
'rewrite' => array('slug'=>'','with_front'=>false)

BTW, found this plugin - If the above code doesn't work it might be useful.
http://wordpress.org/extend/plugins/custom-post-permalinks/


Sean Grant comments:

Thanks for stopping by my question. :)

I tried that code as stated above.

I will check out the plugin you mentioned. Although it looks like it just helps extend what I already got going on; extra folders/directories in the URL that I don't want. And I will still check it out.


AdamGold comments:

Yeah, wasn't sure about the plugin, wasn't the code helpful? The 'with_front' method is the one that controls the prefix (custom-type/)

Can I see your code (after the change) please?


Sean Grant comments:

I tried the code you mentioned. Again since I said I tried it in the main question with no results. And it seemed to do nothing/ I still get domain.com/project/post-slug

Here is the code for you to see.
function wizy_create_portfolio() {
register_post_type(
'project',
array(
'labels' => array(
'name' => __('Projects'),
'singular_name' => __('Project'),
'add_new' => __('New Project'),
'add_new_item' => __('Add New Project'),
'edit' => __('Edit'),
'edit_item' => __('Edit Project'),
'new_item' => __('New Project'),
'view' => __('View Project'),
'view_item' => __('View Project'),
'search_items' => __('Search Projects'),
'not_found' => __('No projects found'),
'not_found_in_trash' => __('No projects found in Trash')
),
'public' => true,
'show_ui' => true,
'publicly_queryable' => true,
'exclude_from_search' => false,
'supports' => array('title', 'editor', 'thumbnail', 'comments', 'page-attributes', 'author'),
'menu_icon' => WIZYP_URI . '/images/projects.png',
'menu_position' => 5,
'rewrite' => array('slug'=>'','with_front'=>false) // seems to do nothing; stil get .com/project/postslug
)
);
}


I tried the plugin too. And while it is setup to add more directories and help with URL conflicts it doesn't quite do what I want.
I set the code above back to default/original and tried installing and activating the plugin. I can see where I can change things in the Permalinks and I change the code to be what I want;
from default of plugin: /%post_type%/%project%
to this: /%project%

AND this did change my URLs to domain.com/post-name-slug like I wanted, but they throw a 404 when I try to visit that URL with these settings.

Now what can I try?


AdamGold comments:

Didn't use the plugin before, so can't tell you what to do - But try the following changes (deactivate the plugin)

Change the rewrite to false:'rewrite' => false

Now add the following code to your functions.php:
global $wp_rewrite;
$project_structure = '/%project%';
$wp_rewrite->add_rewrite_tag("%gallery%", '([^/]+)', "project");
$wp_rewrite->add_permastruct('project', $project_structure, false);



[[LINK href="http://shibashake.com/wordpress-theme/custom-post-type-permalinks-part-2"]]http://shibashake.com/wordpress-theme/custom-post-type-permalinks-part-2[[/LINK]]


AdamGold comments:

Sorry, should be:
global $wp_rewrite;

$project_structure = '/%postname%';

$wp_rewrite->add_rewrite_tag("%postname%", '([^/]+)', "project");

$wp_rewrite->add_permastruct('project', $project_structure, false);


AdamGold comments:

Also, add this to your functions.php:
// Add filter to plugin init function
add_filter('post_type_link', 'project_permalink', 10, 3);
// Adapted from get_permalink function in wp-includes/link-template.php
function project_permalink($permalink, $post_id, $leavename) {
$post = get_post($post_id);
$rewritecode = array(
'%year%',
'%monthnum%',
'%day%',
'%hour%',
'%minute%',
'%second%',
$leavename? '' : '%postname%',
'%post_id%',
'%category%',
'%author%',
$leavename? '' : '%pagename%',
);

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

$category = '';
if ( strpos($permalink, '%category%') !== false ) {
$cats = get_the_category($post->ID);
if ( $cats ) {
usort($cats, '_usort_terms_by_ID'); // order by ID
$category = $cats[0]->slug;
if ( $parent = $cats[0]->parent )
$category = get_category_parents($parent, false, '/', true) . $category;
}
// show default category in permalinks, without
// having to assign it explicitly
if ( empty($category) ) {
$default_category = get_category( get_option( 'default_category' ) );
$category = is_wp_error( $default_category ) ? '' : $default_category->slug;
}
}

$author = '';
if ( strpos($permalink, '%author%') !== false ) {
$authordata = get_userdata($post->post_author);
$author = $authordata->user_nicename;
}

$date = explode(" ",date('Y m d H i s', $unixtime));
$rewritereplace =
array(
$date[0],
$date[1],
$date[2],
$date[3],
$date[4],
$date[5],
$post->post_name,
$post->ID,
$category,
$author,
$post->post_name,
);
$permalink = str_replace($rewritecode, $rewritereplace, $permalink);
} else { // if they're not using the fancy permalink option
}
return $permalink;
}


Sean Grant comments:

Adam,

Thanks for all your persistence. It's greatly appreciated.

I've just found my solution.

I used the plugin you recommended @ http://wordpress.org/extend/plugins/custom-post-permalinks/
and that gave me URLs I wanted (domain.com/post-name-slug) after I set the Extra Permalink Settings to just '/%project%' and the regular Custom Structure to '/%project%' as well.
But that gave 404 errors when I tried to visit them in a browser

Then I added this line to the register_post_type function because I remember reading about WP 3.1 and custom post types not having archives, and having to set them manually somewhere and I saw an example on WP Codex here: http://codex.wordpress.org/Custom_Post_Types and so I tried it.
'has_archive' => true

The combination of the has_archive to true and the plugin's permalink rewrites work together to solve this riddle.

I can now view each post, that has been changed to a custom post type of 'project' at the URL of domain.com/post-slug just like I wanted to from the beginning.

I imagine that what you mentioned to put into the functions.php is what the plugin does/handles dynamically. I thank you for leading me to that plugin. Thanks!

Do you or anyone have any other questions?


Sean Grant comments:

Darn it, I spoke too soon.
So I got the custom post type to pull up when I use the URL I want: <em>domain.com/post-name-slug</em>

<strong>but now my Pages don't work.</strong>

I presume this has something to do with how I want my pages to be the same URL structure: <em>domain.com/page-title-slug</em>

... Is what I want a possibility? Or are custom post types just not supposed/supported to do this?


AdamGold comments:

The pages display 404 errors in both ways? (how they were before and /page-slug)?


Sean Grant comments:

Adam,
Thanks for your continued help.

The Pages (only one; About @ domain.com/about) worked fine from the start and only gives 404 when rewrite => false on the register_post_type AND the Custom Post Type Permalink Plugin is enabled AND when I have it configured to just %project% for both Extra Permalink setting and the Custom Structure Permalink setting. Cuz I want this; domain.com/%project%

I like all my URLs to be top level, 'post' or page. I know I need to be careful not to name a post (in this case custom post type) the same as a page. On this site there will be only 1-3 pages. ever.

I will try the code(s) you suggested earlier to see if I get a different result than using this plugin.

Peace.


Sean Grant comments:

Hey Adam,

I went ahead and used the code you suggested above without the plugin.
It creates the URLs I want, but they don't work.

What I mean is the links are how I want them: domain.com/post-name
BUT
When I try to visit them I just get my post/project archive page. My archive page is domain.com/project/ ... this displays all the latest projects/posts with thumbnail and link.

This happens to both my projects and my page (domain.com/about) with the code above.

Now what?


AdamGold comments:

That's really weird. Try this tutorial:
[[LINK href="http://www.johnpbloch.com/2010/08/custom-post-types-and-better-permalinks/"]]http://www.johnpbloch.com/2010/08/custom-post-types-and-better-permalinks/[[/LINK]]


Sean Grant comments:

That tutorial is just what the guy did before he incorporated it into the plugin that you recommended earlier. And I tried it.

<strong>Final Result:</strong>
Custom Post Types just aren't meant to have be top level URLs.
Sure we could edit WP for days and get what we want eventually, but then what when upgrade time comes?

I came to a solution that is acceptable for now;
Use the Custom Post Type Permalink plugin, set register_post_type to rewrite => false, set said plugin's Extra Permalink Setting to /%post-type% (in my case /%project%) and the WP Custom Structure to /%project%.
This gives the URLs I want but breaks/404s Pages.
To solve that I then change all WP Pages (only 2 in my case) to 'Projects' and use Custom Post Template plugin to select a custom template for all the 'Projects' I want to display like a Page. I simply copy and pasted the page.php template and saved a new version called ProjectAsPage.php and follow plugin instructions to make this template appear in the drop down for Project Templates when editing a Project.

I will be utilizing this solution for now, and in the future I will switch to a different theme that allows me to do what I want.

Thanks for your help Adam.

If anyone has any questions about this feel free to contact me.
Peace,
Sean

2011-05-02

derekshirk answers:

Could you use a php rewrite rule in your functions.php?
Something similar to this:


add_rewrite_rule('(the-post-slug)/?$','index.php?<post type>=$matches[1]','top');


Sean Grant comments:

I will try this and see how it goes.

How do I get WP to actually use the post's slug in the rewrite rule? $slug variable? Like this? And I change the post type to what it is set to: project. correct?
add_rewrite_rule('($slug)/?$','index.php?project=$matches[1]','top');

Thanks for the help.

2011-05-02

Ryan Riatno answers:

So the custom content type is "Project", and you want to have a permalink structure like domain.com/post-type/post-slug?
I have experienced this issue and I just add
flush_rewrite_rules()
right after register post type function


Sean Grant comments:

Thanks for chiming in.
Yes the custom content type is "Project"
but No, I don't want domain.com/post-type/post-slug
I DO want domain.com/post-slug

By default it is already domain.com/project/post-slug I want to get rid of 'project' in the URL.

Have you ever accomplished the URL structure I want with a custom post type?