Here’s a plugin that uses the posts_orderby
filter to support a custom _post_type__in
orderby in WP_Query
that orders the post types by their array placements:
<?php
/**
* Plugin Name: Support for _post_type__in orderby in WP_Query
* Plugin URI: https://wordpress.stackexchange.com/a/392910/26350
*/
add_filter ( 'posts_orderby', function ( $orderby, \WP_Query $q ) use ( $wpdb ) {
// Do nothing.
if ( '_post_type__in' !== $q->get( 'orderby' ) ) {
return $orderby;
}
// Custom _post_type__in ordering using FIELD on post types array items.
$post_type = $q->get( 'post_type' );
if ( ! empty( $post_type ) && is_array( $post_type ) ) {
$post_type__in = array_map( 'sanitize_title_for_query', $post_type );
$post_type__in_string = "'" . implode( "','", $post_type__in ) . "'";
return $orderby = "FIELD( {$wpdb->posts}.post_type," . $post_type__in_string . ' )';
}
return $orderby;
}, 10, 2 );
Usage example:
$args = array(
'post_type' => array( 'expressions', 'videos', 'lingo', 'exercises' ),
'orderby' => '_post_type__in',
);
$query = new WP_Query( $args );
ps: we use orderby post_name__in in core for guidance here. You can then look into expanding this to support multiple orderby fields.