Как получить изображения галереи WordPress в порядке, установленном в админке, используя WP_Query?
Я пытаюсь получить все изображения из Галереи
страницы в том порядке, в котором они установлены в админке.
На данный момент у меня есть:
$my_wp_query = new WP_Query();
$all_wp_pages = $my_wp_query->query(
array(
'post_type' => 'attachment', // Тип записи - вложение
'post_parent' => 54, // ID родительской страницы
'post_mime_type' =>'image', // Только изображения
'post_status' => 'inherit', // Статус наследуемый
'posts_per_page' => '20', // Лимит изображений
'orderby' => 'menu_order', // Сортировка по порядку меню
'order' => 'ASC' // По возрастанию
)
);
var_dump( $all_wp_pages );
Но этот код возвращает все изображения-вложения в стандартном/дефолтном порядке, а не в том, в котором я их перетаскивал в интерфейсе редактирования галереи в админке.
Я предполагаю, что это происходит потому, что я запрашиваю все изображения-вложения моей страницы, а не конкретно Галерею, и поэтому информация о сортировке галереи не передается в возвращаемом массиве.
Может ли кто-нибудь подсказать, как получить все изображения галереи для определенного page_id в том порядке, в котором они установлены в админке? На каждой странице будет только одна галерея, если это поможет.
Спасибо

Когда вы создаёте галерею через медиа-менеджер WordPress 3.5, параметр menu_order
больше не используется для сохранения порядка изображений. Порядок теперь существует только в шорткоде, который вставляется при нажатии кнопки Вставить галерею
, через атрибут ids=
. Это сделано для поддержки возможности добавления нескольких галерей в одну запись — сортировка через menu_order
в таком случае не сработает. Чтобы извлечь эти ID, нам понадобится немного регулярных выражений для поиска шорткодов gallery
в контенте записи, а затем использовать эти ID в запросе post__in
, который теперь можно удобно сортировать по этим ID с помощью нового в WordPress 3.5 значения orderby
— post__in
.
Если бы я был лучше в регулярных выражениях, это, вероятно, не было бы так сложно, но, увы, я в них не силён, поэтому мы воспользуемся нативными функциями WordPress и проделаем несколько трюков для извлечения этих атрибутов ID. Этот метод будет работать как для одной, так и для нескольких галерей в контенте записи. Я только что протестировал это, вставив код в цикл записи. Вам нужно будет заменить $post->post_content
на источник, откуда вы получаете контент записи/страницы.
$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() ):
// цикл по возвращённым изображениям
endif;
wp_reset_query();
endif;
endforeach;
endif;

Вы правы.
Поле menu_order больше не используется для медиафайлов в галерее. К сожалению, похоже, что единственным "источником" порядка галереи является аргумент "ids" в шорткоде галереи, который встроен в контент страницы/записи.
Не уверен, сделано это намеренно или по недосмотру, но возможно это сделано специально, так как теперь можно включать медиафайлы в галерею, даже если они не "прикреплены" к странице/записи. В любом случае, ниже приведён метод, который я использую для получения ID и загрузки вложений в порядке, указанном в шорткоде.
Ключевой момент - параметр "orderby" в вызове get_posts должен быть "post__in", это указывает сортировать по порядку ID записей, указанных в параметре "include". Смотрите ниже.
// Вспомогательная функция для возврата первого совпадения по регулярному выражению
function get_match( $regex, $content ) {
preg_match($regex, $content, $matches);
return $matches[1];
}
// Извлекаем аргументы шорткода из $page или $post
$shortcode_args = shortcode_parse_atts(get_match('/\[gallery\s(.*)\]/isU', $post->post_content));
// Получаем ID, указанные в вызове шорткода
$ids = $shortcode_args["ids"];
// Получаем вложения, указанные в аргументе "ids" шорткода
$attachments = get_posts(
array(
'include' => $ids,
'post_status' => 'inherit',
'post_type' => 'attachment',
'post_mime_type' => 'image',
'order' => 'menu_order ID',
'orderby' => 'post__in', // обязательно для сортировки результатов в порядке, указанном в параметре "include"
)
);
Это не идеальное решение, и было бы лучше, если бы ядро WordPress хранило этот порядок в базе данных, но этот метод работает, пока у нас нет более элегантного способа.
Надеюсь, это поможет!

Если вы всё ещё ищете более простой способ сделать это, вы можете использовать плагин Attachments,
http://wordpress.org/plugins/attachments/
Он хранит галерею отдельно и не добавляет шорткоды галереи в контент записи, что даёт вам полный контроль над отображением изображений в ваших записях/страницах/произвольных типах записей.
Вы также можете изменить порядок изображений простым перетаскиванием.
Вот пример кода для получения изображений галереи:
<?php $attachments = new Attachments( 'attachments' ); /* передаём имя экземпляра */ ?>
<?php if( $attachments->exist() ) : ?>
<h3>Прикрепления</h3>
<p>Всего прикреплений: <?php echo $attachments->total(); ?></p>
<ul>
<?php while( $attachments->get() ) : ?>
<li>
ID: <?php echo $attachments->id(); ?><br />
Тип: <?php echo $attachments->type(); ?><br />
Подтип: <?php echo $attachments->subtype(); ?><br />
URL: <?php echo $attachments->url(); ?><br />
Изображение: <?php echo $attachments->image( 'thumbnail' ); ?><br />
Источник: <?php echo $attachments->src( 'full' ); ?><br />
Размер: <?php echo $attachments->filesize(); ?><br />
Поле заголовка: <?php echo $attachments->field( 'title' ); ?><br />
Поле подписи: <?php echo $attachments->field( 'caption' ); ?>
</li>
<?php endwhile; ?>
</ul>
<?php endif; ?>
