Is it possible to request several post types from a feed?

If so, how should the query URL be formatted? I’ve tried:

  • post_type=cat1&post_type=cat2
  • post_type=cat1,cat2
  • post_type=cat1+cat2

This bug report says you could use post_type[]=cat1&post_type[]=cat2 if not for the fact that “all request parameters are converted to strings”. Is this still the case and what does it mean?

Related posts

Leave a Reply

1 comment

  1. You could use add_feed() and create new feeds … for each post type combination a separate feed. That’s not what I would call flexible, so I recommend to create an endpoint.

    The following code creates an endpoint for the root of a WordPress installation. After refreshing the permalinks you get a regular feed at /multifeed/ (for pages only) or /multifeed/post+page+custom/ for almost any given combination.

    I am not sure why, but it seems not to work for attachments.

    <?php
    /*
     * Plugin Name: T5 Multi Post Type Feed
     */
    
    add_action(
        'init',
        array ( T5_Multi_Post_Type_Feed::get_instance(), 'plugin_setup' )
    );
    class T5_Multi_Post_Type_Feed
    {
        /**
         * Plugin instance.
         *
         * @see get_instance()
         * @type object
         */
        protected static $instance = NULL;
    
        /**
         * Internal handler for WordPress
         *
         * @type string
         */
        protected static $query_var = 'multifeed';
    
        /**
         * Access this plugin’s working instance
         *
         * @wp-hook init
         * @since   2012.10.03
         * @return  object of this class
         */
        public static function get_instance()
        {
            NULL === self::$instance and self::$instance = new self;
    
            return self::$instance;
        }
    
        /**
         * Used for regular plugin work.
         *
         * @wp-hook init
         * @since   2012.10.03
         * @return  void
         */
        public function plugin_setup()
        {
            add_rewrite_endpoint( self::$query_var, EP_ROOT );
            add_filter( 'request', array ( $this, 'set_query_var' ) );
            // Hook in late to allow other plugins to operate earlier.
            add_action( 'template_redirect', array ( $this, 'render' ), 100 );
        }
    
        /**
         * Print the feed items.
         *
         * @wp-hook template_redirect
         * @since   2012.10.03
         * @return void
         */
        public function render()
        {
            if ( ! is_front_page() or ! get_query_var( self::$query_var ) )
            {
                return;
            }
    
            $args       = get_query_var( self::$query_var );
            $post_types = array_filter( explode( '+', $args ) );
            query_posts( array ( 'post_type' => $post_types ) );
            // make the post object accessible in this scope. Hat tip to @Rarst. :)
            global $post;
            require WPINC . '/feed-rss2.php';
            exit;
        }
    
        /**
         * Set the endpoint variable to a default value.
         *
         * If the endpoint was called without further parameters it does not
         * evaluate to TRUE otherwise.
         *
         * @wp-hook request
         * @since   2012.10.03
         * @param   array $vars
         * @return  array
         */
        public function set_query_var( $vars )
        {
            // make the following code shorter
            $q       = self::$query_var;
            $default = apply_filters( 't5_multipost_default_type', 'page' );
    
            if ( isset ( $vars[ $q ] ) and '' === $vars[ $q ] )
            {
                $vars[ $q ] = $default;
            }
    
            // Sometimes WP misinterprets the request as a page request
            // and returns a 404.
            if ( ( isset ( $vars['pagename'] ) and $q === $vars['pagename'] )
                or ( isset ( $vars['page'] )
                    and isset ( $vars['name'] )
                    and $q === $vars['name']
                )
            )
            {
                $vars['page'] = $vars['pagename'] = $vars['name'] = FALSE;
                $vars[ $q ] = $default;
            }
            return $vars;
        }
    
        /**
         * Get the URL for our endpoint.
         *
         * Usage:
         * $url = T5_Multi_Post_Type_Feed::get_instance()->get_endpoint_url(
         *      array( 'post', 'attachment' )
         * );
         *
         * @return  string
         * @wp-hook plugin_row_meta
         * @since   2012.09.21
         * @return  string
         */
        public function get_endpoint_url( $types = array( 'page' ) )
        {
            $post_types = implode( '+', $types );
            // If that is false, there are no pretty permalinks.
            $has_permalinks = get_option( 'permalink_structure' );
            $home = home_url( '/' );
    
            if ( ! $has_permalinks )
            {
                return add_query_arg(
                    array ( self::$query_var => $post_types ),
                    $home
                );
            }
    
            return user_trailingslashit( $home . self::$query_var . "/$post_types" );
        }
    }
    

    Install as plugin, refresh your permalink settings by just visiting that page – and that’s it.