What you want is a rewrite endpoint.
You’re already familiar with these. WordPress’ urls that end with feed
are simple a rewrite endpoint, and you can add your own!
add_rewrite_endpoint
takes two arguments: the endpoint you want, and the “mask” of where you want it to go. “mask” is just a number that you can do some bitwise math with to specify where you want the endpoint to go. As of WP 3.4 you can specify a custom ep_mask
when registering a post type.
The basic gist: hook into init
, call add_rewrite_endpoint
, specify the custom EP mask of your post type. Here’s a really quick example (as a plugin here):
<?php
class WPSE45713
{
const EP = 262144;
private static $ins = null;
public static function instance()
{
is_null(self::$ins) && self::$ins = new self;
return self::$ins;
}
public static function init()
{
add_action('plugins_loaded', array(self::instance(), '_setup'));
register_activation_hook(__FILE__, array(__CLASS__, 'activate'));
register_deactivation_hook(__FILE__, array(__CLASS__, 'deactivate'));
}
public static function activate()
{
self::instance()->register();
self::instance()->endpoints();
flush_rewrite_rules();
}
public static function deactivate()
{
flush_rewrite_rules();
}
public function _setup()
{
add_action('init', array($this, 'register'));
add_action('init', array($this, 'endpoints'), 15);
add_filter('request', array($this, 'filter_request'));
}
public function register()
{
register_post_type('product', array(
'label' => __('Products', 'wpse'),
'public' => true,
'rewrite' => array(
'ep_mask' => self::EP,
),
));
}
public function endpoints()
{
add_rewrite_endpoint('detailed', self::EP);
}
public function filter_request($vars)
{
if(isset($vars['detailed']))
$vars['detailed'] = true;
return $vars;
}
}
The only downside to this is that endpoints are meant to be used as /<endpoint_name>/<some_value>
. So without <some_value>
present the endpoint technically wouldn’t work — hence the filter hooked into request
. Check if the endpoint is set, and set it to true if it is.
That also means that /detailed/asdf
would work just as well as /detailed/
. Not a huge issue to but something to be aware of.
On the front end side of things, you can check to see if the endpoint exists by using get_query_var
:
<?php
if(get_query_var('detailed'))
{
// we're on /product/some-product/detailed/
// do stuff!
}
add_rewrite_endpoint
adds query variables with the same name as you specified for the endpoint. detailed
in this case.