У меня есть настраиваемый тип сообщений для профилей музыкантов и таксономия для их местоположения (иерархически разделены на страны, а затем города). На отдельных страницах профиля музыканта мне нужно отобразить список музыкантов в том же городе (т.е. дочернюю таксономию). Также было бы хорошо отображать сообщения в одной и той же стране отдельно (родительская таксономия).
Проблема, по-видимому, заключается в динамическом извлечении таксономии, разделении родительской и дочерней таксономий и использовании их в новом цикле.
Я могу отобразить список таксономий и удалить ссылки…
$terms = get_the_term_list( $post->ID, 'locations', '', ', ', '' ) ;
echo strip_tags($terms);
… который возвращает такой результат: Нью-Йорк, США
И я могу легко перебирать сообщения по фиксированному значению таксономии…
<?php $my_query = new WP_Query( array( 'locations' => 'new-york', 'showposts' => 10 ) ); ?>
<?php while ($my_query->have_posts()) : $my_query->the_post(); ?>
<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endwhile; ?>
Но у меня возникли проблемы с объединением двух: насколько я могу судить, «get_the_term_list» не имеет возможности возвращать только одну таксономию, и, похоже, не существует таксономического эквивалента «get_the_category».
Любая помощь очень ценится!!!
Привет @George :
В зависимости от того, сколько музыкантов вы ожидаете иметь в своей базе данных, вы можете либо использовать полный маршрут API (что обычно предпочтительнее, когда это целесообразно), если у вас будет их большое количество (тысячи?), вы могли бы пойти с некоторый пользовательский SQL, чтобы получить именно те записи, которые вам нужны.
Использование подхода WordPress API
Основы подхода WordPress API заключаются в том, чтобы сначала вызвать
wp_get_object_terms()
ваш$post->ID
профиль музыканта и вашу'locations'
таксономию, которая вернет список объектов «term». (К сожалению, вам нужно, чтобы это было только одно местоположение, иначе это решение развалится. Но игнорирование этого…)Затем вы берете идентификатор первого термина и передаете его вместе со своей
'locations'
таксономией,get_objects_in_term()
которая возвращает массив идентификаторов сообщений, у которых есть термины, связанные с желаемой таксономией. (Обратите внимание, что это будет включать ВСЕ сообщения, которые имеют ЛЮБОЙ термин, связанный с вашей'locations'
таксономией, поэтому этот подход хорош только для меньшего количества записей.)Затем вы создаете
WP_Query
объект, передавая ему запрос, который используетсяpost__in
для фильтрации по списку идентификаторов музыкантов, которые вы получили выше, а также по вашей'locations'
таксономии и конкретному городскому термину, полученному для вашего профилированного музыканта. Конечно, вы также должны не забыть отфильтровать профилированного музыканта, используя'post__not_in'
аргумент.Все вместе я упаковал эту логику в функцию с именем
get_posts_related_by_taxonomy()
, исходный код которой вы можете увидеть здесь (я упустил несколько деталей, когда объяснял, но, надеюсь, они достаточно очевидны):Теперь вы можете использовать эту функцию в своем собственном цикле, например:
Использование прямого SQL-подхода
Как я уже сказал, я предпочитаю WordPress API, когда он жизнеспособный. К сожалению, я думаю, что вы столкнетесь с проблемами производительности или памяти, если у вас будет даже достаточно большое количество музыкантов, и вы будете использовать подход, показанный выше.
В качестве альтернативы производительности и экономии памяти вы можете использовать прямой SQL для замены всего, включая вызов
get_objects_in_terms()
в предыдущем примере. Хорошей новостью является то, что SQL прост и вряд ли столкнется с проблемами совместимости в будущем с новыми версиями WordPress, поскольку SQL использует только ссылки на первичные и внешние ключи, и это не изменится, если они полностью не обновят систему таксономии, что я думаю навряд ли.Используя SQL, я создал другую версию
get_posts_related_by_taxonomy()
функции, которую вы будете называть точно так же, как и первая версия. SQL распознает, что таблицаwp_term_relationships
просто должна быть объединена их общимterm_taxonomy_id
полем, которое будет связывать все записи музыкантов для данной пары место/ (таксономия) + город/ (термин). Затем присоединяем его кwp_term_taxonomy
table, чтобы мы могли фильтровать таксономию, а также фильтровать по профилированному музыканту на одном конце отношения и фильтровать, чтобы убедиться, что ни один из связанных музыкантов не является профилированным музыкантом на другом конце отношения. Наконец, мы удостоверяемся, что связанные типы сообщений музыкантов равны типу сообщений нашего профилированного музыканта, чтобы вы могли избежать еще одного поиска, в этом случае мы избегаем вызоваget_post()
.Наши результаты из SQL представляют собой хороший простой массив идентификаторов сообщений, который мы снова можем использовать с
post__in
аргументом,WP_Query
но на этот раз нам не нужно включать или фильтрpost__not_in
, и мы можем указать использовать, поскольку наш SQL-запрос уже обработал все эти.taxonomy
term
$args
post_type
'any'
Для второй версии вот код, который вам нужен:
И снова вы будете использовать эту вторую версию
get_posts_related_by_taxonomy()
точно так же, как и первую версию.Надеюсь это поможет!
спасибо за ваш подробный пост. Это сэкономило мне кучу времени, и я многому научился в процессе. Спасибо. В моей версии функций я добавил способ WP3.1 для запроса таксономий: ‘tax_query’ => array( array( ‘taxonomy’ => $taxonomy, ‘field’ => ‘slug’, ‘terms’ => $ terms[0]->slug //$branchterms->slug ))
@Juan — Рад, что смог помочь, и спасибо за ваши дополнения.
привет, я использую ваш скрипт и отлично работает, но ‘post__not_in’ => $post->ID не работает, как я ожидаю, потому что я вижу заголовок для текущего сообщения в этом цикле. что может быть не так? Спасибо
@Joe — Лучше всего, если вы зададите еще один вопрос с вашими конкретными данными, включая ваш конкретный код. Если вы предоставите полностью тестируемый набор кода в своем вопросе, который мы можем добавить на существующий сайт WordPress, это облегчит кому-то помощь. Ссылайтесь на этот вопрос, если вам нужно.
@ user5112 Согласно кодексу WP, вы не можете комбинировать «post__in» и «post__not_in» в одном запросе!
@Rarst :
wp_get_object_terms()
не дает ему того, что он ищет. Он возвращает термины в таксономии списка постов, но ему нужен список постов (музыкантов), которые имеют тот же термин (местоположение), что и данный пост (музыкант).@MikeSchinkel Ну, шаг за шагом. Запрос
get_the_category()
аналога является частью вопроса. Насколько я понимаю, Джорджу нужно сначала получить условия текущего музыканта, чтобы он мог использовать их для запроса связанных музыкантов.@Rarst : Вы правы, это первый шаг. Но могу ли я сказать, что это очень похоже на то, как сказать кому-то, кто спросил дорогу из Англии в Италию, просто «пересечь Ла-Манш» ; это заставит их начать, но куда они пойдут дальше? Просто говорю… 🙂
@Mike: Конечно, ваш ответ великолепен, но у нас не всегда есть время, чтобы дать полные ответы, и иногда люди могут узнать что-то самостоятельно, как только вы дадите им первую подсказку.
@MikeSchinkel Я очень мало знаю о пользовательских таксономиях (буду изучать их в ближайшем будущем, но не так далеко), что как бы помешало мне написать идеальный ответ. 🙂 Итак, я ответил на часть, которую знал.
Проверьте
wp_get_object_terms()
, это более общая функция и то, чтоget_the_category()
используется внутри.