I want to query attachments and exclude all images.
I can see how to include only images, using 'post_mime_type' => 'image/*'
, but I couldn't find any way of achieving the opposite. Is there any mime_type equivalent of posts__not_in
?
Pretty much the solution is to include all mimes except images. WordPress has a nifty little function where it keeps all it's accepted mime-types called get_allowed_mime_types()
( cleverly named ) which returns an Array() of mimes. All we need to do is get the difference between the returned array and the array of mime-types we don't want in our query:
$unsupported_mimes = array( 'image/jpeg', 'image/gif', 'image/png', 'image/bmp', 'image/tiff', 'image/x-icon' );
$all_mimes = get_allowed_mime_types();
$accepted_mimes = array_diff( $all_mimes, $unsupported_mimes );
$attachment_query = new WP_Query( array(
'post_type' => 'attachment',
'post_status' => 'inherit',
'post_mime_type' => $accepted_mimes,
'posts_per_page' => 20,
) );
If you also want to include post types other than attachments (e.g. posts, pages) that don't have any mime type, you'll have to use the posts_where
filter:
add_filter( 'posts_where' , 'remove_images' );
function remove_images($where) {
global $wpdb;
$where.=' AND '.$wpdb->posts.'.post_mime_type NOT LIKE \'image/%\'';
return $where;
}
I'm pretty much certain there isn't an equivalent of posts_not_in
for mime types.
You could of course query for all attachments that are images. Preferably just returning the IDs via parameter fields
set to ids
. Then you can use those IDs with posts__not_in
on a second query. Drawback being that you need two queries.
Another possibility would be to hook into the posts_where
filter and apply some SQL to get your result like you want it.
posts_where
filter as per your question in the end because of other details I'd left out of my question, but am keeping the other answer as accepted as it answers the question I posed.
Commented
Nov 24, 2015 at 15:56