WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am trying to find a way to filter the Media Library by the Post Category that a Media item is assigned with. I can see that you can sort by "attached to" but this only get me a little of the way there. Any suggestions?

share|improve this question
up vote 1 down vote accepted

You can use pre_get_posts to filter the query.

So you can

  1. retrieve a category from query vars
  2. the retrieve the post with that category
  3. set the media query to include only post having that posts as parent

To give an UI you can use restrict_manage_posts hook to output a category dropdown.

add_action('pre_get_posts', 'my_filter_media_by_cat');
add_action( 'restrict_manage_posts', 'my_add_media_cat_dropdown' );

function my_filter_media_by_cat( $q ) {
  $scr = get_current_screen();
  $cat = filter_input(INPUT_GET, 'postcat', FILTER_SANITIZE_STRING );   
  if ( ! $q->is_main_query() || ! is_admin() || (int)$cat <= 0 || $scr->base !== 'upload' )
  // get the posts
  $posts = get_posts( 'nopaging=1&category=' . $cat );
  // get post ids
  $pids = ( ! empty( $posts ) ) ? wp_list_pluck($posts, 'ID') : false;
  if ( ! empty($pids) ) {
    $pidstxt = implode($pids, ',');
    global $wpdb;
    // get the ids of media having retrieved posts as parent
    $mids = $wpdb->get_col("SELECT ID FROM $wpdb->posts WHERE post_parent IN ($pidstxt)");
    if ( ! empty($mids) ) {
      // force media query to retrieve only media having retrieved posts as parent
      $q->set( 'post__in', $mids );
    } else {
      // force media query to return no posts
      $q->set( 'p', -1 ); // let query found nothing

function my_add_media_cat_dropdown() {
  $scr = get_current_screen();
  if ( $scr->base !== 'upload' ) return;
  $cat = filter_input(INPUT_GET, 'postcat', FILTER_SANITIZE_STRING );   
  $selected = (int)$cat > 0 ? $cat : '-1';  
  $args = array(
      'show_option_none'   => 'All Post Categories',
      'name'               => 'postcat',
      'selected'           => $selected
  wp_dropdown_categories( $args );

Negative of this code is that you have to rune 3 queries to filter the media...

Result on UI:

enter image description here

share|improve this answer
thanks, I will check this out - looks like it is what I am looking for. One question though - where is postcat coming from in the my_add_media_cat_dropdown function – whodeee Dec 18 '13 at 15:09
$cat = filter_input(INPUT_GET, 'postcat', FILTER_SANITIZE_STRING ); is an alternate (better and safer) way of $cat = $_GET['postcat'];. See PHP docs @whodeee – gmazzap Dec 18 '13 at 15:15
thanks! Worked great! Any suggestions for this question I had? – whodeee Dec 18 '13 at 15:37
@G.M. : get_current_screen only works on the backend but pre_get_posts runs front and back. You need an is_admin check. – s_ha_dum Jan 6 '14 at 15:05

gmazzap's solution inspired me to write a plugin to do this. You can now filter your media by Taxonomies and Terms with the Media Library Filter plugin.

share|improve this answer

Your Answer


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.