I recently asked this question Custom post types – Use post_id in permalink structure and solved it but as I have enabled 'has_archive' => true the solution given no longer works. Let me explain:
I’m after this structure:
archive-events.php=> /news/events/single-events.php=> /news/events/%post_id%/%postname%
To get post_id in a single event permalink I’ve had to add %post_id% to the CPT slug but when enabling has_archive => true the archive page becomes the slug; in this case becoming /news/events/%post_id%/ which is invalid.
So my question:
How do I have post_id in permalink structure when using has_archive => true
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
To get what you need you have to add a custom rewrite rule and to filter the permalink construction. The following code does both:
<?php # -*- coding: utf-8 -*-
/**
* Plugin Name: Event Permalinks
*/
// Not a WordPress context? Stop.
! defined( 'ABSPATH' ) and exit;
// Wait until all needed functions are loaded.
add_action( 'init', array ( 'Bradys_Events', 'init' ) );
class Bradys_Events
{
/**
* Creates a new instance.
*
* @wp-hook init
* @see __construct()
* @return void
*/
public static function init()
{
new self;
}
/**
* Constructor
*/
public function __construct()
{
$args = array(
'label' => 'events',
'public' => true,
'hierarchical' => false,
'has_archive' => true,
'rewrite' => array(
'with_front' => false,
'slug' => "news/events"
),
'supports' => array( 'title', 'editor', 'thumbnail' )
);
register_post_type("events", $args);
// Prevent WordPress from sending a 404 for our new perma structure.
add_rewrite_rule(
'^news/events/(d+)/[^/]+/?$',
'index.php?post_type=events&p=$matches[1]',
'top'
);
// Inject our custom structure.
add_filter( 'post_type_link', array ( $this, 'fix_permalink' ), 1, 2 );
}
/**
* Filter permalink construction.
*
* @wp-hook post_type_link
* @param string $post_link default link.
* @param int $id Post ID
* @return string
*/
public function fix_permalink( $post_link, $id = 0 )
{
$post = &get_post($id);
if ( is_wp_error($post) || $post->post_type != 'events' )
{
return $post_link;
}
// preview
empty ( $post->slug )
and $post->slug = sanitize_title_with_dashes( $post->post_title );
return home_url(
user_trailingslashit( "news/events/$post->ID/$post->slug" )
);
}
}
Visit wp-admin/options-permalink.php one time to let WordPress update its rewrite rules.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0