Включить таксономию в поиск
Подскажите как включить в поиск определенную таксономию, чтобы в результатах поиска, отображались не только записи, но и ссылки на таксономию.
Возможно есть готовое решение, желательно без плагинов.
Подскажите как включить в поиск определенную таксономию, чтобы в результатах поиска, отображались не только записи, но и ссылки на таксономию.
Возможно есть готовое решение, желательно без плагинов.
в смысле - поиск термина таксономии, или нужно, чтобы в результатах поиска по записям отображались термины, привязанные к постам в результатах поиска?
Нужно сделать примерно так:
Результаты будут на отдельной странице поиска, либо в общей странице, просто отдельно будут выводиться
$args = array( 'hide_empty=0' ); $terms = get_terms('akter', 'search='.get_search_query().'&number=5', $args); // собираем их и выводим if ( !empty( $terms ) && !is_wp_error( $terms ) ) { $count = count($terms); $i=0; $term_list = '<p class="my_term-archive">'; foreach ($terms as $term) { $i++; $term_list .= '<a href="' . get_term_link( $term ) . '" title="' . sprintf(__('View all post filed under %s', 'my_localization_domain'), $term->name) . '">' . $term->name . '</a>'; if ($count != $i) { $term_list .= ' · '; } else { $term_list .= '</p>'; } } echo $term_list; }Данный код уже выводит результат, но его нужно немного доработать.
Почему-то работает только в таком формате:
$args = array( 'hide_empty=0' ); $terms = get_terms('akter', 'search='.get_search_query().'&number=5', $args);К примеру если пытаюсь вывести в более удобном варианте - не работает:
Так же хотелось бы сделать поиск одновременно по названию и описанию таксономии, но если добавляю сразу два параметра
search и description__likeто ничего не ищет. Тоесть я одновременно передаю два поисковых запроса одинаковых и хочу чтобы находило по заголовку и по описанию, к примеру если заголовок такс. не совпадает, а в описании нужная фраза находится, тогда пусть покажет эту таксономию, но так не получается
и не будет, поскольку запрос неправильный
потому что description__like добавляет в запрос условие AND, т.е. результат возвращается, если поисковая строка одновременно находится в названии И в описании термина.
Вам нужно внедряться в SQL запрос и изменять условия. Посмотрите в сторону хука https://wp-kama.ru/hook/terms_clauses
Ваш вариант тоже не сработал.
С хуком ничего не получилось, я не знаю как его настроить.
Мне кажется идеально было бы настроить поиск не по полю дескрипшен, а по дополнительному полю которое у меня есть в таксономии. Чтобы чтобы запрос в search искал по названию, ярлыку + по доп полю. Такое вообще возможно?
протестировал. Всё отлично работает. Замените функцию get_terms на обращение к классу WP_Term_Query напрямую
$terms = new WP_Term_Query(массив параметров)и при помощи функции
var_dump($terms);выведите на экран содержимое (разумеется, безопаснее всего это делать на локальной копии сайта). Посмотрите, что там, может результат подскажет, что не так.Разумеется, возможно. Добавьте в параметры запроса массив $meta_query
Вот такой вариант работает, но ищет только по полю search, если его убрать, то выдает все подряд результаты.
$terms = get_terms ( 'akter', array( 'search' => get_search_query(), 'hide_empty' => false, $meta_query = array( 'relation' => 'OR', array( 'key' => 'txseo_strana_aktera', 'value' => get_search_query(), 'compare' => 'LIKE' )) )); if ( !empty( $terms ) && !is_wp_error( $terms ) ) { $count = count($terms); $i=0; $term_list = '<p class="my_term-archive">'; foreach ($terms as $term) { $i++; $term_list .= '<a href="' . get_term_link( $term ) . '" title="' . sprintf(__('View all post filed under %s', 'my_localization_domain'), $term->name) . '">' . $term->name . '</a>'; if ($count != $i) { $term_list .= ' · '; } else { $term_list .= '</p>'; } } echo $term_list; }Извините, скопировал пример у Тимура и забыл кое-что исправить. В массиве параметров запроса параметр meta_query передается как элемент массива.
т.е. массив параметров должен выглядеть как-то так:
но он всё равно не сработает, потому что оба запроса объединяются условием AND (OR, как оказалось
, относится только ко внутренним запросам параметра meta_query).
Вам придется дополнительно внедриться в выборку WHERE SQL-запроса и заменить условие перед запросом значения мета-поля.
Внедрение в выборку делается примерно так
add_filter( 'terms_clauses', 'metadata_search', 10, 3 ); function metadata_search( $clauses, $taxonomies, $args ){ global $wpdb; if( ! is_search() || ! is_main_query() || $args['taxonomy'][0] != 'akter' ) return $clauses; // Проверка обязательна, иначе всё сломается $clauses['where'] = str_replace( ")) AND (", ")) OR (", $clauses['where']); // Здесь я просто заменил условие перед запросом по значению метаполя с AND на OR. return $clauses; }Протестировано, в лабораторных условиях работает. Если не сработает, вызовите внутри функции metadata_search на экран var_dump($clauses['where'] и поизучайте. Возможно, в ваших условиях может потребоваться более сложная замена.
Если слишком сложно, то ничто не мешает получить результаты поиска несколькими запросами - один для названия/слага, один для описания, один для метаполя.
В итоге поиск по полю сделать не получается, непонятно в чем проблема, может старая версия вп (обновлять не хочу, перестают работать другие настройки )
В итоге у меня работает только такой формат
Однако meta_query не срабатывает, тоесть выводятся полностью все актеры из раздела. Работает только search (если его отключить выводиться весь список).
Я предполагаю в данный код нужно как-то по другому встроить meta_query, но все мои варианты не дают никаких результатов.
Вот такой формат, почему-то у меня не работает
У меня 4.4 версия, поэтому и работает вариант как написал выше, но почему же meta_query не срабатывает...
разве это может быть так, что "txseo_strana_aktera" и элементы таксономии "akter" содержат одинаковые строки? К примеру, имя актера и название страны содержат строку "Великобритания"?
запрос же выполняется с условием AND.
если она поддерживает метаполя у термина, значит не такая уж и старая.
говорил выше, скажу еще раз - лучший способ понять, что не так с запросом - передать его не в функцию-обертку, а в класс напрямую. Возвращённый результат будет содержать не только совпавшие элементы, но и всю служебную информацию по обработанному запросу (параметры, сформированный SQL-запрос и т.д.)
запрос же выполняется с условием AND.
К примеру если отключить search и оставить только поиск по txseo_strana_aktera значит должен выдаваться поиск по этому полю (я временно указал там ключевое слово для теста), но в итоге выдается полный список всех актеров. Пробовал в параметрах meta_query вывести актера по ID но все равно выдает результат всех актеров.
Воспользовался функцией var_dump($terms);
Если искать по названию
вот результат:
array(1) { [0]=> object(stdClass)#2719 (9) { ["term_id"]=> string(4) "1393" ["name"]=> string(14) "Сталоне" ["slug"]=> string(7) "stalone" ["term_group"]=> string(1) "0" ["term_taxonomy_id"]=> string(4) "1393" ["taxonomy"]=> string(5) "akter" ["description"]=> string(0) "" ["parent"]=> string(1) "0" ["count"]=> string(1) "0" } }Если по полю
array(0) { }Если убрать search и делать поиск по полю, то выдает инфу сразу по всем актерам. В итоге meta_query никак не влияет на результат, и неважно какие параметры указывать просто весь список актеров
запрос $terms = new WP_Term_Query (массив переменных) вернет объект WP_Term_Query
что-то типа (копирую с тестового сайта):
object(WP_Term_Query)#NUMBER { ["request"]=> string(794) "SELECT DISTINCT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_termmeta ON ( t.term_id = wp_termmeta.term_id ) INNER JOIN wp_term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy IN ('akter') AND ((t.name LIKE '{hash}поиск{hash}') OR (t.slug LIKE '{hash}поиск{hash}')) AND ( ( wp_termmeta.meta_key = 'txseo_strana_aktera' AND wp_termmeta.meta_value LIKE '{hash}поиск{hash}' ) ) ORDER BY t.name ASC " ["meta_query"]=> object(WP_Meta_Query)#NUMBER (9) { ["queries"]=> array(2) { [0]=> array(3) { ["key"]=> string(19) "txseo_strana_aktera" ["value"]=> string(10) "поиск" ["compare"]=> string(4) "LIKE" } ["relation"]=> string(2) "OR" }и еще несколько десятков страшных строк, и в самом конце этого страшного есть
где либо NULL, либо объекты элементов, совпавших с условием.
Если в [request] не включаются условия из [meta_query], значит версия WP ниже 4.6 и нужно помолясь и выпив водки обновиться хотя бы до этой версии.
Обновил ВП до 4,8
Результат нулевой
meta_query не работает нивкакую.
Возможно есть вариант написать дополнительную функцию, чтобы расширить поиск через параметр search по умолчанию он ищет по названию и ярлыку, а с помощью доп. функции добавить туда поле. Я в этом не особо понимаю, сможете помочь за вознаграждение?
Что возвращает запрос new WP_Term_Query?
есть такое подозрение, что раз Вы _обновились_ до 4.8, то древний плагин (или не менее древний найденный в интернете код), которым к элементам таксономии добавляются метаданные, создал свою таблицу в базе данных, поскольку тогда таблицы wp_termmeta в установке WordPress еще не было.
Проверьте, есть ли таблица wp_termmeta, не пустая ли она. Самый простой способ проверить - получить значение метаполя у элемента с помощью
echo get_term_meta ($term_id, $key_name, true)Метаполе должно быть точно заполнено. Если пусто, то метаданные сохранены нестандартным способом и их нужно импортировать в таблицу wp_termmetaНемного разобрался и настроил meta_query, хотя конечно в новой версии вп другие проблемы вылезли, я планировал обновиться, но когда будет больше времени сделать все настройки. Сейчас все таки удобней будет сделать настройку в старой версии.
В итоге покопался в файле taxonomy.php и нашел функцию function get_terms
Где и есть параметры поля search
if ( ! empty( $args['search'] ) ) { $like = '%' . $wpdb->esc_like( $args['search'] ) . '%'; $where .= $wpdb->prepare( ' AND ((t.name LIKE %s) OR (t.slug LIKE %s))', $like, $like ); }t.slug можно заменить на tt.description и поиск начинает работать по описанию. По аналогии думаю можно заменить это на ID нужного мне поля, но конечно же не все так просто, нужно создать хук, а тут уже моих навыков не хватает
Еще вопрос, как создать условие if в котором будет определяться количество символов введенных в форме поиска?
Я хочу чтобы поиск срабатывал при вводе 3 символов и больше.
добавьте атрибут minlength="3" к полю ввода
у меня поле общее для поиска записей и поиска такс, на одной страницы выдает результаты. Выдачу записей хотелось бы оставить как есть.
и каким образом атрибут, на который обращает внимание только браузер, помешает поиску?
Хотелось бы чтобы поиск срабатывал как и раньше, но результаты по актерам отображались с введенным минимальным количеством символов.
при добавлении атрибута искать записи уже не получиться
обрезаете значение поисковой строки до нужного размера функцией mb_substr() и отправляете в запрос(ы), которыми получаете результаты поиска
Сейчас через обычную форму поиска передаю поисковый запрос и получаю результат, но если в конце запроса к примеру поставить пробел, то ничего уже не находит. Можно как-то сделать, чтобы лишние пробелы не учитывались?
универсальная, имеющаяся во всех современных языках, функция trim() обрезает пробелы и спецсимволы с обоих краев переданной строки. Если нужно, чтобы строка обрезалась только с одной стороны, используйте PHP-функции ltrim() для обрезки с начала строки и rtrim() - с конца.
а если между словами 2 пробела? лишний можно убрать?
$string = preg_replace('/[\s]{2,}/gm', ' ', $string);Не совсем понятно куда встраивать эту строку