GDY
GDY

Reputation: 2941

WordPress : query by attachment meta (image size)

Is it possible to use WP_Query to get attachment images by pixel size?

For example all images with a width of 500px and height of 300px. Or images with a height bigger than 300px.

As far as i can see i can catch this data in the meta query with 'key' => '_wp_attachment_metadata' but what then? There seems no solution that is precise enough to target that width or height inside _wp_attachment_metadata ...

Upvotes: 5

Views: 3474

Answers (2)

David
David

Reputation: 5937

You cannot do it with wp_query as height and width do not have their own meta field (they are part of a serialized array). But this is easy enough to overcome, we can just assign them their own postmeta db entry when uploading (you can also use wp_query to get all images and loop over to update existing images)

add_filter('wp_generate_attachment_metadata', 'add_metac', 10, 2);


function add_metac($meta, $id){

    update_post_meta($id, 'height', (int) $meta['height']);
    update_post_meta($id, 'width', (int) $meta['width']);
    return $meta;

}

You can then query for images greater than dimensions etc, something like this:

$types = array( 'image/jpeg', 'image/gif', 'image/png');
$args= array(
    'post_type'         => 'attachment',
    'post_status'    => 'inherit',
    'post_mime_type'    => $types,
    'meta_query' => array(
        'relation' => 'AND', //-->this is default but showing here as you can use OR
        array(
            'key'     => 'height',
            'value'   => 300,
            'type'    => 'numeric',
            'compare' => '>',
        ),
        array(
            'key'     => 'width',
            'value'   => 300,
            'type'    => 'numeric',
            'compare' => '>',
        ),
    )

);

$images= new WP_Query($args);

Upvotes: 2

user5200704
user5200704

Reputation: 1709

@Dan is mentioned correctly WP_Query and mysql can't handle this way. But we need a all display media with conditional size above @Dan's answer fit this solution but when we need also pagination parameter and display limit records each page so have solution below change query request.

<?php

global $query_args;

$query_args = array(
    'post_type'      => 'attachment',
    'post_mime_type' => array('image/jpeg', 'image/gif', 'image/png'),
    'post_status'    => 'inherit',
    'fields' => 'ids'
);  // add pagination parameters in $query_args

add_filter( 'posts_request', function( $request ){

 global $wpdb, $query_args;

 remove_filter( 'posts_request', __FUNCTION__ );

 $all_media = $wpdb->get_results($request);

 if( empty( $all_media ) )
 return $request;

 $exclude_ids = array();

 foreach( $all_media as $media ){
     $meta = wp_get_attachment_metadata( $media->ID );
     if( $meta['width'] != 500 ||  $meta['height'] < 300 ) // Add condition also allow add more condition with different sizes
     $exclude_ids[] = $media->ID;
 }   

 if( $exclude_ids ){
   $query_args['post__not_in'] = $exclude_ids;
   $q = new WP_Query( $query_args );
   $request =  $q->request;
   wp_reset_query();      
 }

 return $request;  

});


$query = new WP_Query( $query_args );
//echo $query->request;
if( $query->have_posts() ){
  while( $query->have_posts() ){
      $query->the_post();
      echo get_the_title();
  }     

}

wp_reset_query();  

I didn't tested more records. I hope this helpful for you.

Upvotes: 0

Related Questions