29

It seems like stupid question. But, I can't figure it out :(.

I need to display button at home that goes to custom post_type's archive URL (archive-{post_type}.php). How do I do that?

2
  • What sort of button, add one to a nav menu, or just a generic link? The archive URL is generally yoursite.com/type-slug unless you explicitly set it to something else, eg. yoursite.com/some-other-url..
    – t31os
    Mar 8, 2011 at 23:30
  • @t31os: yup, right now, I hardcoded it like that. But, will soon change it using @Mike's code.
    – ariefbayu
    Mar 8, 2011 at 23:51

2 Answers 2

29

Hi @Silent:

Turns out there is a function in WordPress 3.1 that does exactly what you want and it is named get_post_type_archive_link(); here's how you'd call it (assuming a custom post type named 'product'):

<a href="<?php echo get_post_type_archive_link('product'); ?>">Products</a>

Below is my prior answer before I discovered that WordPress did indeed have a function built-in for this use case.

Prior Answer:

Unless I overlooked something in the core source code for WordPress 3.1 I think you are looking for a function like get_archive_link() which you might call like this (assuming a custom post type named 'product'):

<a href="<?php echo get_archive_link('product'); ?>">Products</a>

And here's the source code which you can place into your theme's function.php file or in a .php file for a plugin you might be writing:

if (!function_exists('get_archive_link')) {
  function get_archive_link( $post_type ) {
    global $wp_post_types;
    $archive_link = false;
    if (isset($wp_post_types[$post_type])) {
      $wp_post_type = $wp_post_types[$post_type];
      if ($wp_post_type->publicly_queryable)
        if ($wp_post_type->has_archive && $wp_post_type->has_archive!==true)
          $slug = $wp_post_type->has_archive;
        else if (isset($wp_post_type->rewrite['slug']))
          $slug = $wp_post_type->rewrite['slug'];
        else
          $slug = $post_type;
      $archive_link = get_option( 'siteurl' ) . "/{$slug}/";
    }
    return apply_filters( 'archive_link', $archive_link, $post_type );
  }
}

I was actually working on this exact logic over the weekend although I'm not yet 100% sure the order of the logic is generically correct across all use-cases that WordPress might see although it will probably work for any specific site.

This is also a great thing to suggest be added to WordPress via trac which I think I will do later this evening.

7
  • btw, when you submit the trac, can you please, link it here.
    – ariefbayu
    Mar 8, 2011 at 23:52
  • @silent - Yes, of course. Mar 8, 2011 at 23:59
  • @Mike - I'd have wrote something similar if you hadn't.... ;) I was wondering if this is what @silent had in mind, but the mention of a button had me thinking of something else..
    – t31os
    Mar 9, 2011 at 0:00
  • @t31os - I was working on the same logic this weekend for my URL routing plugin, so I had a head start. :) As for the button, you could add an answer to address that? Mar 9, 2011 at 0:08
  • I'm not really sure there's anything left to cover, i think your above function covers what was asked... :)
    – t31os
    Mar 9, 2011 at 0:13
12

when you register post type you can pass a string as slug with "has_archive" parameter and make sure you also set rewrite to either true or an array but not false and then your CPT archive URL would be http://www.YOURDOMAIN.com/has_archive_slug for example

if you set in your register_post_type for example:

$args = array(
    'labels' => $labels,
    'public' => true,
    'publicly_queryable' => true,
    'show_ui' => true, 
    'show_in_menu' => true, 
    'query_var' => true,
    'rewrite' => 'product',
    'capability_type' => 'post',
    'has_archive' => 'products', 
    'hierarchical' => false,
    'menu_position' => null,
    'supports' => array('title','editor','author','thumbnail','excerpt','comments')
  ); 
 register_post_type('product',$args);

then your single url is: http://www.YOURDOMAIN.com/product/postName and your archive url is: http://www.YOURDOMAIN.com/products/

2
  • 3
    Hooray. I had always thought has_archive was a boolean, but now I know it can be given a string, so my singular custom post type recipe can have a plural slug /recipes/
    – Astrotim
    Dec 17, 2014 at 0:30
  • I don't recall if/when they made the switch or if this was always in error, but in 2017 'rewrite' only accepts a boolean or array value. Rather than the 'rewrite' => 'product', you have listed, it should instead be 'rewrite' => array( 'slug' => 'product' ),.
    – Mike
    Nov 15, 2017 at 1:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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