WordPress.org

Ready to get started?Download WordPress

Forums

[closed] PAGES and CUSTOM TYPES cannot have the same name, so how to structure permalinks (20 posts)

  1. gian-ava
    Member
    Posted 3 years ago #

    As everybody knows you cannot have PAGES and CUSTOM TYPES with the same name, otherwise you can get a 404 (error) page with pagination and other kinds of problems.

    While it makes sense that WP gets troubled from having to manage 2 URLs with the same name, how limiting is the fact that there is no solution to keep a logical permalinks consistency?

    For example:
    You want to have a SECTION of your website called "Agenda", to hold events under that section, and therefore would like this permalinks structure:

    websitename.com/agenda (index of events)
    websitename.com/agenda/event-name-1 (event 1)
    websitename.com/agenda/event-name-2( event 2)
    … and do on.

    You create a CUSTOM TYPE called "agenda", so that the events index lives under that slug (websitename.com/agenda/event-name-1).

    But you also need to create a PAGE with a slug of "agenda" with a page template with a loop for the "agenda" CUTOM TYPE, in order to get "websitename.com/agenda" which is the index of events.

    But WordPress tells you, you can't!

    The community is aware of this limitation and the easy solution for everybody to deal with such a problem is to change either the PAGE name or the CUSTOM TYPE name, like advised everywhere:

    - http://wpveda.com/solved-wordpress-custom-post-type-and-404-issue/
    - http://www.wordimpressed.com/wordpress/solve-wordpress-custom-post-type-404-error-issues/
    - http://modernsparkmedia.com/393/wordpress-pagination-with-custom-post-type/
    - http://justintadlock.com/archives/2010/04/29/custom-post-types-in-wordpress#comment-188256

    But changing the CUSTOM TYPE NAME to something like "events" is not a solution, is it? Because you end up having "websitename.com/events/event-name-1" when you wanted "websitename.com/agenda/event-name-1".

    So, I wonder, how come nobody seems to care about such a limitation? What if a CLIENT wants to have that kind of URL structure, with all the events under "Agenda"? How do you go and explain that he cannot, that WordPress is limited when it comes to wanted something like this?

    Really, I can't believe that in the whole WordPress community nobody is facing this problem and nobody has a solution, or put it out there.

  2. jdaily
    Member
    Posted 3 years ago #

    Just wanted to add that I hope this gets some attention. In my case, I have a site where posts from the category "paintings" populate both my blog and a page titled "paintings" ... which seems reasonable enough to me.

    It's not the end of the world to rename either of the above ... but it is annoying, and I hope in the future this won't be necessary.

  3. jdaily
    Member
    Posted 3 years ago #

    Okay, I misunderstood the problem. My pagination error stemmed from having a static page with the slug "blog" and also assigning "blog" as my category base in my dashboard "Permalink Settings".

    I understand how this could complicate things for WordPress, but it was nice to have my URL structure give the impression that all my posts were contained in a "blog" directory:

    MAIN PAGE:
    jqdaily.com/blog
    SAMPLE CATEGORY:
    jqdaily.com/blog/articles-demos

    Now instead I have this:

    MAIN PAGE:
    jqdaily.com/blog
    SAMPLE CATEGORY:
    jqdaily.com/category/articles-demos

    Again, not the end of the world, but it would still be nice to house everything under "blog" in my URL structure ... and this worked up until version 3.

  4. gian-ava
    Member
    Posted 3 years ago #

    I am really surprised that nobody is interested in this topic/issue, beside me and jdaily.

    Do WP users really have no problem to settle with this limitation? I can't believe that among all the designers and developers nobody needs or want to have a logical permalinks "by sections".

    And how do you go and explain to a CLIENT that your choosen CMS for their project just doesn't allow you do have that, if that is what they need?

  5. ldexterldesign
    Member
    Posted 3 years ago #

    Just solved this actually.

    register_post_type('products', array(
      'rewrite' => array('slug' => 'products')
    ));

    or alternatively if you're using this plugin ( http://wordpress.org/extend/plugins/custom-post-type-ui/ ) you'll want to ensure under 'Manage Post Types > Advanced Options' that you provide a 'Custom Rewrite Slug'.

    My URL now looks something like this, with the extra level clearing naming clashes up:

    http://localhost/project/products/product-1/

    Best,

  6. fonglh
    Member
    Posted 3 years ago #

    I got around it by using a plural form for the index page. So in the case of events, the index page would be events, while the custom post type name would be 'event'.

    this gives you websitename.com/events as the index page, and websitename.com/event/event-name-1 for an individual event, which should be logical enough to sell to your client as an alternative.

    The Custom Post Type Archives plugin seems to redirect websitename.com/custom-type-name to an archive page. You could try that, then customize the archive template so it looks like an index page.

  7. ldexterldesign
    Member
    Posted 3 years ago #

    My last comment was only half a solution to the problem. I'm still looking for a solution to pagination on a template page whilst querying for custom post types?

    If anyone finds a solution please drop a note in below.

    @fonglh I'll assume you aren't using a template page to query for your custom post types; using your index page instead?

    Thanks,

  8. fonglh
    Member
    Posted 3 years ago #

    I am using a template page, was just using gian-ava's naming terms where he refers to a page of all the custom post type posts as the index.

    For pagination, you'll have to include the 'paged' parameter when calling query_posts.

    query_posts(array('post_type'=>'event','posts_per_page'=>2,'paged'=>get_query_var('paged')));

  9. ldexterldesign
    Member
    Posted 3 years ago #

    @fonglh would you mind posting your template page?

  10. ldexterldesign
    Member
    Posted 3 years ago #

    Here's my code anyway:

    functions.php

    register_post_type('products', array(	'label' => 'Products','description' => '','public' => true,'show_ui' => true,'show_in_menu' => true,'capability_type' => 'post','hierarchical' => false,'rewrite' => array('slug' => 'products'),'query_var' => true,'supports' => array('title','editor','excerpt','trackbacks','custom-fields','comments','revisions','thumbnail','author','page-attributes',),'labels' => array (
      'name' => 'Products',
      'singular_name' => 'Product',
      'menu_name' => 'Products',
      'add_new' => 'Add Product',
      'add_new_item' => 'Add New Product',
      'edit' => 'Edit',
      'edit_item' => 'Edit Product',
      'new_item' => 'New Product',
      'view' => 'View Product',
      'view_item' => 'View Product',
      'search_items' => 'Search Products',
      'not_found' => 'No Products Found',
      'not_found_in_trash' => 'No Products Found in Trash',
      'parent' => 'Parent Product',
    ),) );

    page-products.php

    <?php
    /*
    Template Name: Products
    */
    
    get_header(); ?>
    
    <div id="container">
    	<div id="content" role="main">
    
    		<?php query_posts(array('post_type'=>'products','posts_per_page'=>1,'paged'=>get_query_var('paged'))); ?>
    		<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
    
    		<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
    			<h2 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php printf( esc_attr__( 'Permalink to %s', 'twentyten' ), the_title_attribute( 'echo=0' ) ); ?>" rel="bookmark">
    				<?php the_title(); ?>
    				</a></h2>
    			<div class="entry-meta">
    				<?php twentyten_posted_on(); ?>
    			</div>
    			<!-- .entry-meta -->
    			<?php if ( is_archive() || is_search() ) : // Only display excerpts for archives and search. ?>
    			<div class="entry-summary">
    				<?php the_excerpt(); ?>
    			</div>
    			<!-- .entry-summary -->
    			<?php else : ?>
    			<div class="entry-content">
    				<?php the_content( __( 'Continue reading <span class="meta-nav">&rarr;</span>', 'twentyten' ) ); ?>
    				<?php wp_link_pages( array( 'before' => '<div class="page-link">' . __( 'Pages:', 'twentyten' ), 'after' => '</div>' ) ); ?>
    			</div>
    			<!-- .entry-content -->
    			<?php endif; ?>
    			<div class="entry-utility">
    				<?php if ( count( get_the_category() ) ) : ?>
    				<span class="cat-links"> <?php printf( __( '<span class="%1$s">Posted in</span> %2$s', 'twentyten' ), 'entry-utility-prep entry-utility-prep-cat-links', get_the_category_list( ', ' ) ); ?> </span> <span class="meta-sep">|</span>
    				<?php endif; ?>
    				<?php
    					$tags_list = get_the_tag_list( '', ', ' );
    					if ( $tags_list ):
    				?>
    				<span class="tag-links"> <?php printf( __( '<span class="%1$s">Tagged</span> %2$s', 'twentyten' ), 'entry-utility-prep entry-utility-prep-tag-links', $tags_list ); ?> </span> <span class="meta-sep">|</span>
    				<?php endif; ?>
    				<span class="comments-link">
    				<?php comments_popup_link( __( 'Leave a comment', 'twentyten' ), __( '1 Comment', 'twentyten' ), __( '% Comments', 'twentyten' ) ); ?>
    				</span>
    				<?php edit_post_link( __( 'Edit', 'twentyten' ), '<span class="meta-sep">|</span> <span class="edit-link">', '</span>' ); ?>
    			</div>
    			<!-- .entry-utility -->
    		</div>
    		<!-- #post-## -->
    		<?php comments_template( '', true ); ?>
    
    		<?php endwhile; // End the loop. Whew. ?>
    		<?php endif; ?>
    
    	</div>
    	<!-- #content -->
    </div>
    <!-- #container -->
    <?php // get_sidebar(); ?>
    <?php // get_footer(); ?>
  11. ldexterldesign
    Member
    Posted 3 years ago #

    Forgot to include my pagination links didn't I - doh. All good. Bedtime!

    page-products.php

    <?php
    /*
    Template Name: Products
    */
    
    get_header(); ?>
    
    <div id="container">
    	<div id="content" role="main">
    
    		<?php query_posts(array('post_type'=>'products','posts_per_page'=>1,'paged'=>get_query_var('paged'))); ?>
    
    		<?php /* Display navigation to next/previous pages when applicable */ ?>
    		<?php if ( $wp_query->max_num_pages > 1 ) : ?>
    		<div id="nav-above" class="navigation">
    			<div class="nav-previous">
    				<?php next_posts_link( __( '<span class="meta-nav">&larr;</span> Older posts', 'twentyten' ) ); ?>
    			</div>
    			<div class="nav-next">
    				<?php previous_posts_link( __( 'Newer posts <span class="meta-nav">&rarr;</span>', 'twentyten' ) ); ?>
    			</div>
    		</div>
    		<!-- #nav-above -->
    		<?php endif; ?>
    
    		<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
    
    		<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
    			<h2 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php printf( esc_attr__( 'Permalink to %s', 'twentyten' ), the_title_attribute( 'echo=0' ) ); ?>" rel="bookmark">
    				<?php the_title(); ?>
    				</a></h2>
    			<div class="entry-meta">
    				<?php twentyten_posted_on(); ?>
    			</div>
    			<!-- .entry-meta -->
    			<?php if ( is_archive() || is_search() ) : // Only display excerpts for archives and search. ?>
    			<div class="entry-summary">
    				<?php the_excerpt(); ?>
    			</div>
    			<!-- .entry-summary -->
    			<?php else : ?>
    			<div class="entry-content">
    				<?php the_content( __( 'Continue reading <span class="meta-nav">&rarr;</span>', 'twentyten' ) ); ?>
    				<?php wp_link_pages( array( 'before' => '<div class="page-link">' . __( 'Pages:', 'twentyten' ), 'after' => '</div>' ) ); ?>
    			</div>
    			<!-- .entry-content -->
    			<?php endif; ?>
    			<div class="entry-utility">
    				<?php if ( count( get_the_category() ) ) : ?>
    				<span class="cat-links"> <?php printf( __( '<span class="%1$s">Posted in</span> %2$s', 'twentyten' ), 'entry-utility-prep entry-utility-prep-cat-links', get_the_category_list( ', ' ) ); ?> </span> <span class="meta-sep">|</span>
    				<?php endif; ?>
    				<?php
    					$tags_list = get_the_tag_list( '', ', ' );
    					if ( $tags_list ):
    				?>
    				<span class="tag-links"> <?php printf( __( '<span class="%1$s">Tagged</span> %2$s', 'twentyten' ), 'entry-utility-prep entry-utility-prep-tag-links', $tags_list ); ?> </span> <span class="meta-sep">|</span>
    				<?php endif; ?>
    				<span class="comments-link">
    				<?php comments_popup_link( __( 'Leave a comment', 'twentyten' ), __( '1 Comment', 'twentyten' ), __( '% Comments', 'twentyten' ) ); ?>
    				</span>
    				<?php edit_post_link( __( 'Edit', 'twentyten' ), '<span class="meta-sep">|</span> <span class="edit-link">', '</span>' ); ?>
    			</div>
    			<!-- .entry-utility -->
    		</div>
    		<!-- #post-## -->
    		<?php comments_template( '', true ); ?>
    
    		<?php endwhile; // End the loop. Whew. ?>
    		<?php endif; ?>
    
    		<?php /* Display navigation to next/previous pages when applicable */ ?>
    		<?php if (  $wp_query->max_num_pages > 1 ) : ?>
    		<div id="nav-below" class="navigation">
    			<div class="nav-previous">
    				<?php next_posts_link( __( '<span class="meta-nav">&larr;</span> Older posts', 'twentyten' ) ); ?>
    			</div>
    			<div class="nav-next">
    				<?php previous_posts_link( __( 'Newer posts <span class="meta-nav">&rarr;</span>', 'twentyten' ) ); ?>
    			</div>
    		</div>
    		<!-- #nav-below -->
    		<?php endif; ?>
    
    	</div>
    	<!-- #content -->
    </div>
    <!-- #container -->
    <?php // get_sidebar(); ?>
    <?php // get_footer(); ?>

    Many thanks,

  12. gian-ava
    Member
    Posted 3 years ago #

    I'm happy the topic got some interest.

    ldexterldesign, giving plural to the slug is not the solution I am looking for. The names "events" and "event" are not what I am looking for, since the section is called "agenda", and can't have the plural of that. So, if the slug "agenda" is used by the a PAGE that serves as an index with the loop for the agenda items (events CUSTOM POSTS), how can you go and have the slug "agenda" for your CUSTOM POST TYPES so that you get this:

    websitename.com/agenda
    websitename.com/agenda/event-name-1
    websitename.com/agenda/event-name-2

    That screws up pagination. And, I do have the pagination fix;

    $paged = (get_query_var('paged')) ? get_query_var('paged') : 1; //for WP-PageNavi


    <?php if(function_exists('wp_pagenavi')) { wp_pagenavi(array( 'query' => $agendaloop )); } ?>

    See what I mean?

  13. ldexterldesign
    Member
    Posted 3 years ago #

    @gian-ava if you're not using the plugin ( http://wordpress.org/extend/plugins/wp-pagenavi/ ) this your solution isn't a fix either.

    Ideally I'd like to resolve this without installing more plugins. It's an issue with core.

    Thanks,

  14. gian-ava
    Member
    Posted 3 years ago #

    @ldexterldesign Actually, the above fix is not a solution.
    I meant, even with the pagination fix (which is a common fix), the pagination gets screwed if you got CUSTOM TYPE and PAGE with the same name.

    So, I am as stuck with this as you are.
    ;-(

    PS: and the WP-PageNavi plugin doesn't have anything to do, I just mentioned it.

  15. fonglh
    Member
    Posted 3 years ago #

    when you register the post type, add

    'has_archive' => true

    to the array of arguments.

    using the prev example,

    register_post_type('products', array(	'label' => 'Products','description' => '','public' => true,'show_ui' => true,'show_in_menu' => true,'capability_type' => 'post','hierarchical' => false,'rewrite' => array('slug' => 'products'),'query_var' => true,'supports' => array('title','editor','excerpt','trackbacks','custom-fields','comments','revisions','thumbnail','author','page-attributes',),'has_archive'=>true,'labels' => array (
      'name' => 'Products',
      'singular_name' => 'Product',
      'menu_name' => 'Products',
      'add_new' => 'Add Product',
      'add_new_item' => 'Add New Product',
      'edit' => 'Edit',
      'edit_item' => 'Edit Product',
      'new_item' => 'New Product',
      'view' => 'View Product',
      'view_item' => 'View Product',
      'search_items' => 'Search Products',
      'not_found' => 'No Products Found',
      'not_found_in_trash' => 'No Products Found in Trash',
      'parent' => 'Parent Product',
    ),) );

    This should allow you to reach an archive page of your custom posts with websitename.com/post-type

    I haven't tested this with pagination.

  16. fonglh
    Member
    Posted 2 years ago #

    oh you'll have to refresh the permalinks as well. just visit the permalinks settings page.

  17. darrinb
    Member
    Posted 2 years ago #

  18. Peter vanDoorn
    Member
    Posted 2 years ago #

    Here's a strange thing then.

    In my ignorance (having never heard of this issue) I created a page called "events" and a custom post type also called "events" and haven't ever had any problems with it!

    I'm currently using WP 3.1.3 and use Custom Post Type UI plugin 0.7. Permalink structure is set to /%category%/%postname%/. Only other thing I can think of that might effect this is SEO Ultimate.

    Am I lucky or have they fixed this? It must be said, though, that I don't use pagination but the URLs work perfectly.

    Peter

  19. beR-
    Member
    Posted 2 years ago #

    Hi community,

    It semms I've just found the solution to keep the same name for pages and custom post_type.
    In the definition of your custom post_type, just use add_rewrite_rule to redefine the traitment of the url :

    add_rewrite_rule("{$post}" . '$', "index.php?pagename={$post}", "top");
    add_rewrite_rule("{$post}" . '/page/([0-9])*/?', "index.php?pagename={$post}" . '&paged=$matches[1]', "top");
    
    global $wp_rewrite;
    $wp_rewrite->flush_rules(); // !!!

    Here {$post} correspond to your post_type "agenda" or "event". You can simplify syntaxe. Here is my whole function :

    /**
     * Rewrite buzz permalink with '/{post_type}/%year%/%monthnum%/%day%/%buzz%/' structure
     */
    function ml_rewrite_permalink($post){
    	// Rewrite buzz permalink with '/buzz/%year%/%monthnum%/%day%/%buzz%/' structure
    	add_rewrite_tag( "%{$post}%", '([^/]+)' );
    	$extra_post_types = get_post_types( array( '_builtin' => false, 'publicly_queryable' => true ) );
    	if( empty( $extra_post_types ) )
    		return;
    	add_rewrite_tag( '%post_type%', '('.implode('|',$extra_post_types).')' );
    	add_permastruct( $post, "/%post_type%/%year%/%monthnum%/%day%/%{$post}%/", true, 1 );
    	add_rewrite_rule("{$post}" . '$', "index.php?pagename={$post}", "top");
    	add_rewrite_rule("{$post}" . '/page/([0-9])*/?', "index.php?pagename={$post}" . '&paged=$matches[1]', "top");
    	global $wp_rewrite;
    	$wp_rewrite->flush_rules(); // !!!
    }

    If any question, feel free to continue the thread.

    nice day,

    beR-

  20. Robert Simpson
    Member
    Posted 2 years ago #

    Hi beR-,

    If you get a minute, could you have a glance at this? - http://wordpress.org/support/topic/universal-permalink-structure-across-post-types-not-pages?replies=3

    Cheers,
    Robert

Topic Closed

This topic has been closed to new replies.

About this Topic