How to get Page/Post Gallery attachment images in order they are set in backend using WP_Query()?

I am trying to retrieve all the images from the Gallery of a page in the order they are set in the backend.

So far I have:

Read More
  $my_wp_query = new WP_Query();

  $all_wp_pages = $my_wp_query->query(
    array(
      'post_type' => 'attachment',
      'post_parent' => 54,  
      'post_mime_type' =>'image',
      'post_status' => 'inherit', 
      'posts_per_page' => '20' 
      'orderby' => 'menu_order',
      'order' => 'ASC'
    )
  );

  var_dump( $all_wp_pages );

But this seems to return all the attachment images in the standard/default order rather than the order I have dragged and dropped the images in the backend edit gallery interface.

I believe this might be due to the fact that I am querying all attachment images of my page rather than specifically the Gallery, and as such the sorting information for the gallery is not passed in the returned array.

Can anyone tell me how I get all the gallery images of a certain page_id in the order they are set in the backend? There will only be one gallery per page if that helps.

thanks

Related posts

Leave a Reply

4 comments

  1. When you create a gallery via the 3.5 media manager, menu_order is no longer used to save the order of the images, the order only exists in the shortcode you insert when you click the Insert Gallery button, via the ids= attribute. This is to accommodate the fact that you can now add multiple galleries to a single post- ordering via menu_order wouldn’t work for this case. To extract these IDs, we’ll have to use a bit of regex to search post content for gallery shortcodes, then use those IDs in a post__in query, which can now be conveniently ordered by those IDs via the new-in-3.5 orderby value post__in.

    If I were better at regex, this probably wouldn’t be so complicated, but alas, I’m terrible at it, so we’ll use some native WP functions and do a few backflips to extract these id attributes. This will work for a single or multiple galleries in post content. I just tested this by dropping it into the loop of a post, you’ll want to change $post->post_content to whatever/wherever you’re getting the post/page content from.

    $pattern = get_shortcode_regex();
    
    if( preg_match_all( '/'. $pattern .'/s', $post->post_content, $matches )
        && array_key_exists( 2, $matches )
        && in_array( 'gallery', $matches[2] ) ):
    
            $keys = array_keys( $matches[2], 'gallery' );
    
            foreach( $keys as $key ):
                $atts = shortcode_parse_atts( $matches[3][$key] );
                    if( array_key_exists( 'ids', $atts ) ):
    
                        $images = new WP_Query(
                            array(
                                'post_type' => 'attachment',
                                'post_status' => 'inherit',
                                'post__in' => explode( ',', $atts['ids'] ),
                                'orderby' => 'post__in'
                            )
                        );
    
                        if( $images->have_posts() ):
                            // loop over returned images
                        endif;
    
                        wp_reset_query();
    
                    endif;
            endforeach;
    
    endif;
    
  2. You are correct.

    The menu_order is no longer used for media in the gallery. Unfortunately, it looks like the only “source” of the gallery order is the “ids” argument for the gallery shortcode which is embedded in the page/post content.

    Not sure if this is by design or an oversight, but it could be by design since you can now include media in a gallery even if it is not “attached” to the page/post. In any case, below is the method I use to grab the ids and get the attachments based on the order specified in the shortcode.

    The key is that the “orderby” param on the call to get_posts must be “post__in” this tells it to order by the post id order specified in the “include” param. See below.

    // helper function to return first regex match
    function get_match( $regex, $content ) {
        preg_match($regex, $content, $matches);
        return $matches[1];
    } 
    
    // Extract the shortcode arguments from the $page or $post
    $shortcode_args = shortcode_parse_atts(get_match('/[gallerys(.*)]/isU', $post->post_content));
    
    // get the ids specified in the shortcode call
    $ids = $shortcode_args["ids"];
    
    // get the attachments specified in the "ids" shortcode argument
    $attachments = get_posts(
        array(
            'include' => $ids, 
            'post_status' => 'inherit', 
            'post_type' => 'attachment', 
            'post_mime_type' => 'image', 
            'order' => 'menu_order ID', 
            'orderby' => 'post__in', //required to order results based on order specified the "include" param
        )
    );
    

    This isn’t ideal and it would be nice if WP core would store this ordering in the database somewhere, but it works until we have a nicer way.

    Hope that helps!

  3. $oImages = get_posts(
        array(
             'numberposts' => -1,
             'post_parent' => $post->ID,
             'post_status' => 'inherit',
             'post_type' => 'attachment',
             'post_mime_type' => 'image',
             'order' => 'ASC',
             'orderby' => 'menu_order'
             )
    );
    

    This snippet has always worked for me.

  4. If you are still looking for a simpler way of doing this, you can use attachments plugin,

    http://wordpress.org/plugins/attachments/

    It keeps the gallery separate and does not put the image gallery shortcodes in post content, thus providing you with full hold over image display in your post/page/custom post.
    You can also change the order of your images by just drag-n-drop

    here is a sample code of how to retrieve your gallery images,

    <?php $attachments = new Attachments( 'attachments' ); /* pass the instance name */ ?>
    <?php if( $attachments->exist() ) : ?>
      <h3>Attachments</h3>
      <p>Total Attachments: <?php echo $attachments->total(); ?></p>
      <ul>
        <?php while( $attachments->get() ) : ?>
          <li>
            ID: <?php echo $attachments->id(); ?><br />
            Type: <?php echo $attachments->type(); ?><br />
            Subtype: <?php echo $attachments->subtype(); ?><br />
            URL: <?php echo $attachments->url(); ?><br />
            Image: <?php echo $attachments->image( 'thumbnail' ); ?><br />
            Source: <?php echo $attachments->src( 'full' ); ?><br />
            Size: <?php echo $attachments->filesize(); ?><br />
            Title Field: <?php echo $attachments->field( 'title' ); ?><br />
            Caption Field: <?php echo $attachments->field( 'caption' ); ?>
          </li>
        <?php endwhile; ?>
      </ul>
    <?php endif; ?>