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?
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( "https://wordpress.stackexchange.com/" );
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.