Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I want to create custom post types with multiple views based on URL.

E.g., suppose I have a "Product" post type. I would like to have something like the following:

I would be fine with this as well:

Is it possible to represent a page/post as different URLs, each with a different view of the same data? Would this require a lot of modification?

share|improve this question
add comment

2 Answers

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.

share|improve this answer
add comment

Probably not the best way to do it, but one way to get there is: set your CPT to hierarchical, so it will allow parents, and allow it to have templates using either this, this or another approach.

Once you've set up things this way, organize your CPTs so that each one is parent to the "detailed", "summary" and "xml" sub-pages (i'm almost certain you can do this automagically, hooking to the saving post hook which name i can't rememember right now).

With that, you can just adjust templates for each "kind" of subpage (you may want to id them with custom values) so that they collect the info the way you want it.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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