Вопрос или проблема
Я не уверен, возможно ли это вообще (также опубликовано на форуме ACF https://support.advancedcustomfields.com/forums/topic/ordering-by-custom-field-of-relationship-field-object/#post-62454)
У меня есть два пользовательских типа записей: произведения искусства и художники. Произведения искусства имеют поле объекта поста ACF ‘artists_name’, связывающее его с одним художником. У художников есть пользовательские поля ‘artist_last_name’ и ‘artist_first_name’. На архивной странице произведений искусства записи сортируются по meta_value с meta_key ‘artists_name’, но, конечно, она сортирует по ID поста.
Я пытаюсь заставить запрос сортировать по фамилии связанного художника, затем по имени. (Т.е. я хочу использовать значение метаданных из типа записи B для сортировки типа записи A.)
Пока что у меня есть этот запрос, который работает, как и ожидалось:
$args = array(
'post_type' => 'artworks',
'posts_per_page' => -1,
'meta_key' => 'artists_name',
'orderby' => 'meta_value'
);
Затем я пытаюсь получить фильтр posts_join
, чтобы найти метаданные поста, чей ID поста = meta_value ‘artists_name’
add_filter('posts_join', 'trial_join', 10, 2 );
function trial_join($joins) {
if(is_post_type_archive('artworks') || (is_admin() && $_GET['post_type'] == 'artworks')) {
global $wpdb;
$joins .= " INNER JOIN {$wpdb->postmeta} artists_name ON artists_name.post_id={$wpdb->posts}.ID WHERE artists_name.meta_key='artist_last_name'" ;
$joins .= " INNER JOIN {$wpdb->postmeta} first_name ON first_name.post_id={$wpdb->posts}.ID WHERE (first_name.meta_key='artist_first_name' AND first_name.post_ID=artists_name.meta_value)";
$joins .= " INNER JOIN {$wpdb->postmeta} last_name ON last_name.post_id={$wpdb->posts}.ID WHERE (last_name.meta_key='artist_last_name' AND last_name.post_ID=artists_name.meta_value)";
}
return $joins;
}
И затем использовать фильтр posts_orderby
:
add_filter('posts_orderby', 'orderby_pages_callback', 10, 2);
function orderby_pages_callback($orderby_statement, $wp_query) {
$orderby_statement = "last_name.meta_value first_name.meta_value ASC";
return $orderby_statement;
}
Но это не работает. Я собрал соединение из кучи других сообщений. Есть какие-нибудь предложения?
Это работает. Фильтры привязаны к пользовательскому 'orderby'
термину и удаляются после запроса.
$args = array(
'post_type' => 'artworks',
'posts_per_page' => -1,
'no_found_rows' => true,
'order' => 'ASC',
'orderby' => 'artist_name_artwork_title',
);
add_filter('posts_join', 'name_join', 10, 2 );
add_filter('posts_orderby', 'orderby_artist_name_artwork_title', 10, 2);
// запрос
$wp_query = new WP_Query( $args );
remove_filter('posts_join', 'name_join', 10 );
remove_filter('posts_orderby', 'orderby_artist_name_artwork_title', 10 );
function name_join($joins, $wp_query) {
if ( $wp_query->get( 'orderby' ) != 'artist_name_artwork_title' ) {
return $joins;
}
global $wpdb;
$joins .= " LEFT JOIN $wpdb->postmeta name ON name.post_id=$wpdb->posts.ID AND name.meta_key='artists_name'" ;
$joins .= " LEFT JOIN $wpdb->postmeta lastname ON lastname.post_id=name.meta_value AND lastname.meta_key='artist_last_name'";
$joins .= " LEFT JOIN $wpdb->postmeta firstname ON firstname.post_id=name.meta_value AND firstname.meta_key='artist_first_name'";
return $joins;
}
function orderby_artist_name_artwork_title($orderby_statement, $wp_query) {
if ( $wp_query->get( 'orderby' ) != 'artist_name_artwork_title' ) {
return $orderby_statement;
}
global $wpdb;
$orderby_statement = "lastname.meta_value, firstname.meta_value, $wpdb->posts.post_title";
return $orderby_statement;
}
Ответ или решение
Заказ Постов Типа "Искусство" по Пользовательским Полям Связанного Поста Типа "Художники"
В данной статье мы разберем, как упорядочить посты одного пользовательского типа (в данном случае "Искусство") по пользовательским полям, связанным с другим пользовательским типом ("Художники"). Для этого мы воспользуемся специфическими фильтрами во WordPress для изменения SQL-запроса, чтобы извлечь данные из пользовательских полей, принадлежащих связанным записям.
1. Описание проблемы
Вы имеете два пользовательских типа:
- Искусство (Artworks) с пост объектом
artists_name
, который связывает его с одним художником. - Художники (Artists), содержащими пользовательские поля:
artist_last_name
иartist_first_name
.
При этом вы столкнулись с необходимостью упорядочить посты типа "Искусство" не по ID художника, а по его фамилии и имени, что требует подключения информации из полей другого пользовательского типа.
2. Решение через WP_Query
Ваше начальное решение с использованием WP_Query выглядит следующим образом:
$args = array(
'post_type' => 'artworks',
'posts_per_page' => -1,
'meta_key' => 'artists_name',
'orderby' => 'meta_value'
);
3. Использование фильтров posts_join и posts_orderby
Для достижения желаемого упорядочивания необходимо использовать фильтры posts_join
и posts_orderby
. Давайте разберем реализацию:
3.1. Фильтр posts_join
Этот фильтр позволяет изменить SQL-запрос, добавив необходимые соединения (JOIN) к таблицам метаданных:
add_filter('posts_join', 'name_join', 10, 2);
function name_join($joins, $wp_query) {
if ($wp_query->get('orderby') != 'artist_name_artwork_title') {
return $joins;
}
global $wpdb;
$joins .= " LEFT JOIN $wpdb->postmeta AS name ON name.post_id = $wpdb->posts.ID AND name.meta_key = 'artists_name' ";
$joins .= " LEFT JOIN $wpdb->postmeta AS lastname ON lastname.post_id = name.meta_value AND lastname.meta_key = 'artist_last_name' ";
$joins .= " LEFT JOIN $wpdb->postmeta AS firstname ON firstname.post_id = name.meta_value AND firstname.meta_key = 'artist_first_name' ";
return $joins;
}
3.2. Фильтр posts_orderby
Фильтр posts_orderby
используется для определения порядка сортировки:
add_filter('posts_orderby', 'orderby_artist_name_artwork_title', 10, 2);
function orderby_artist_name_artwork_title($orderby_statement, $wp_query) {
if ($wp_query->get('orderby') != 'artist_name_artwork_title') {
return $orderby_statement;
}
global $wpdb;
$orderby_statement = "lastname.meta_value, firstname.meta_value, $wpdb->posts.post_title";
return $orderby_statement;
}
4. Завершение запроса
Ваша финальная реализация будет выглядеть следующим образом:
$args = array(
'post_type' => 'artworks',
'posts_per_page' => -1,
'no_found_rows' => true,
'order' => 'ASC',
'orderby' => 'artist_name_artwork_title',
);
// Выполняем запрос
$wp_query = new WP_Query($args);
// Убираем фильтры после выполнения запроса
remove_filter('posts_join', 'name_join', 10);
remove_filter('posts_orderby', 'orderby_artist_name_artwork_title', 10);
Заключение
Используя предложенные решения, вы сможете настроить упорядочивание постов типа "Искусство" на основе полей поста типа "Художники". Данная методика позволит создать более интуитивный и удобный интерфейс для отображения данных на ваших страницах. Не забывайте тестировать код в безопасной среде перед развертыванием на рабочем сайте, чтобы избежать непредвиденных ошибок и сбоев в работе.
Если у вас остались вопросы или требуется дополнительная помощь, не стесняйтесь обращаться к сообществу или форумах WordPress.