WordPress как на ладони
rgbcode is looking for WordPress developers.

Включить таксономию в поиск

Подскажите как включить в поиск определенную таксономию, чтобы в результатах поиска, отображались не только записи, но и ссылки на таксономию.

Возможно есть готовое решение, желательно без плагинов.

1
lethalblo
3.3 года назад 15
  • 1

    в смысле - поиск термина таксономии, или нужно, чтобы в результатах поиска по записям отображались термины, привязанные к постам в результатах поиска?

    lethalblo 3.3 года назад

    Нужно сделать примерно так:

    Результаты будут на отдельной странице поиска, либо в общей странице, просто отдельно будут выводиться

    $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);

    К примеру если пытаюсь вывести в более удобном варианте - не работает:

    $terms = get_terms( array(  
    	'taxonomy'    => 'akter',
    	'search'  => ''.get_search_query().'',
    ), $args );

    Так же хотелось бы сделать поиск одновременно по названию и описанию таксономии, но если добавляю сразу два параметра
    search и description__like

    то ничего не ищет. Тоесть я одновременно передаю два поисковых запроса одинаковых и хочу чтобы находило по заголовку и по описанию, к примеру если заголовок такс. не совпадает, а в описании нужная фраза находится, тогда пусть покажет эту таксономию, но так не получается

    Andrew 3.3 года назад

    К примеру если пытаюсь вывести в более удобном варианте - не работает

    и не будет, поскольку запрос неправильный

    $terms = get_terms( array(  
    	'taxonomy'    => 'akter',
    	'search'  => get_search_query(),
    	'hide_empty' => false // или 0, если удобнее
    ) );

    Тоесть я одновременно передаю два поисковых запроса одинаковых и хочу чтобы находило по заголовку и по описанию, к примеру если заголовок такс. не совпадает, а в описании нужная фраза находится, тогда пусть покажет эту таксономию, но так не получается

    потому что description__like добавляет в запрос условие AND, т.е. результат возвращается, если поисковая строка одновременно находится в названии И в описании термина.

    Вам нужно внедряться в SQL запрос и изменять условия. Посмотрите в сторону хука https://wp-kama.ru/hook/terms_clauses

    lethalblo 3.3 года назад

    Ваш вариант тоже не сработал.

    С хуком ничего не получилось, я не знаю как его настроить.

    Мне кажется идеально было бы настроить поиск не по полю дескрипшен, а по дополнительному полю которое у меня есть в таксономии. Чтобы чтобы запрос в search искал по названию, ярлыку + по доп полю. Такое вообще возможно?

    Andrew 3.3 года назад

    Ваш вариант тоже не сработал.

    протестировал. Всё отлично работает. Замените функцию get_terms на обращение к классу WP_Term_Query напрямую
    $terms = new WP_Term_Query(массив параметров)

    и при помощи функции var_dump($terms); выведите на экран содержимое (разумеется, безопаснее всего это делать на локальной копии сайта). Посмотрите, что там, может результат подскажет, что не так.

    Такое вообще возможно?

    Разумеется, возможно. Добавьте в параметры запроса массив $meta_query

    $meta_query = array(
    	'relation' => 'OR', // ИЛИ, указать обязательно, потому что по умолчанию значение - И. Если оставить как есть, то поиск будет происходить по имени ИЛИ слагу И значению поля.
    	array(
    		'key'     => 'key_name',
    		'value'   => get_search_query(),
    		'compare' => 'LIKE' // для неточного поиска указанной в value подстроки
    	)
    );
    lethalblo 3.3 года назад

    Вот такой вариант работает, но ищет только по полю 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;
    }
    Andrew 3.3 года назад

    Извините, скопировал пример у Тимура и забыл кое-что исправить. В массиве параметров запроса параметр meta_query передается как элемент массива.

    т.е. массив параметров должен выглядеть как-то так:

    array( 
    	'taxonomy' => 'akter',       
    	'search'  => get_search_query(),
    	'hide_empty' => false,
    	'meta_query' => array(
    		'relation' => 'OR', 
    		array(
    			'key'     => 'txseo_strana_aktera',
    			'value'   => get_search_query(),
    			'compare' => 'LIKE' 
    		)
    	)
    )

    но он всё равно не сработает, потому что оба запроса объединяются условием AND (OR, как оказалось smile, относится только ко внутренним запросам параметра 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'] и поизучайте. Возможно, в ваших условиях может потребоваться более сложная замена.

    Andrew 3.3 года назад

    Если слишком сложно, то ничто не мешает получить результаты поиска несколькими запросами - один для названия/слага, один для описания, один для метаполя.

    lethalblo 3.3 года назад

    В итоге поиск по полю сделать не получается, непонятно в чем проблема, может старая версия вп (обновлять не хочу, перестают работать другие настройки )

    В итоге у меня работает только такой формат

    $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' 
    		)
    	)));

    Однако meta_query не срабатывает, тоесть выводятся полностью все актеры из раздела. Работает только search (если его отключить выводиться весь список).

    Я предполагаю в данный код нужно как-то по другому встроить meta_query, но все мои варианты не дают никаких результатов.

    Вот такой формат, почему-то у меня не работает

    array( 
    	'taxonomy' => 'akter',       
    	'search'  => get_search_query(),
    	'hide_empty' => false,
    	'meta_query' => array(
    		'relation' => 'OR', 
    		array(
    			'key'     => 'txseo_strana_aktera',
    			'value'   => get_search_query(),
    			'compare' => 'LIKE' 
    		)
    	)
    );
    lethalblo 3.3 года назад

    taxonomy(строка/массив) (обязательный)
    Название таксономии с которой работать. Можно указать несколько названий в виде массива. С версии WP 4.5, до этого названия таксономий указывались в первом параметре самой функции.

    У меня 4.4 версия, поэтому и работает вариант как написал выше, но почему же meta_query не срабатывает...

    Andrew 3.3 года назад

    Однако meta_query не срабатывает, тоесть выводятся полностью все актеры из раздела. Работает только search (если его отключить выводиться весь список).

    разве это может быть так, что "txseo_strana_aktera" и элементы таксономии "akter" содержат одинаковые строки? К примеру, имя актера и название страны содержат строку "Великобритания"?

    запрос же выполняется с условием AND.

    может старая версия вп

    если она поддерживает метаполя у термина, значит не такая уж и старая.

    в данный код нужно как-то по другому встроить meta_query

    говорил выше, скажу еще раз - лучший способ понять, что не так с запросом - передать его не в функцию-обертку, а в класс напрямую. Возвращённый результат будет содержать не только совпавшие элементы, но и всю служебную информацию по обработанному запросу (параметры, сформированный SQL-запрос и т.д.)

    lethalblo 3.3 года назад

    разве это может быть так, что "txseo_strana_aktera" и элементы таксономии "akter" содержат одинаковые строки? К примеру, имя актера и название страны содержат строку "Великобритания"?

    запрос же выполняется с условием AND.

    К примеру если отключить search и оставить только поиск по txseo_strana_aktera значит должен выдаваться поиск по этому полю (я временно указал там ключевое слово для теста), но в итоге выдается полный список всех актеров. Пробовал в параметрах meta_query вывести актера по ID но все равно выдает результат всех актеров.

    lethalblo 3.3 года назад

    Воспользовался функцией 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 никак не влияет на результат, и неважно какие параметры указывать просто весь список актеров

    Andrew 3.3 года назад

    запрос $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"
    	}

    и еще несколько десятков страшных строк, и в самом конце этого страшного есть

    ["terms"]=> 

    где либо NULL, либо объекты элементов, совпавших с условием.

    Если в [request] не включаются условия из [meta_query], значит версия WP ниже 4.6 и нужно помолясь и выпив водки обновиться хотя бы до этой версии.

    lethalblo 3.3 года назад

    Обновил ВП до 4,8
    Результат нулевой
    meta_query не работает нивкакую.

    Возможно есть вариант написать дополнительную функцию, чтобы расширить поиск через параметр search по умолчанию он ищет по названию и ярлыку, а с помощью доп. функции добавить туда поле. Я в этом не особо понимаю, сможете помочь за вознаграждение?

    Andrew 3.3 года назад

    Что возвращает запрос new WP_Term_Query?

    meta_query не работает нивкакую

    есть такое подозрение, что раз Вы _обновились_ до 4.8, то древний плагин (или не менее древний найденный в интернете код), которым к элементам таксономии добавляются метаданные, создал свою таблицу в базе данных, поскольку тогда таблицы wp_termmeta в установке WordPress еще не было.

    Проверьте, есть ли таблица wp_termmeta, не пустая ли она. Самый простой способ проверить - получить значение метаполя у элемента с помощью echo get_term_meta ($term_id, $key_name, true) Метаполе должно быть точно заполнено. Если пусто, то метаданные сохранены нестандартным способом и их нужно импортировать в таблицу wp_termmeta

    lethalblo 3.3 года назад

    Немного разобрался и настроил 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 нужного мне поля, но конечно же не все так просто, нужно создать хук, а тут уже моих навыков не хватает

    lethalblo 3.3 года назад

    Еще вопрос, как создать условие if в котором будет определяться количество символов введенных в форме поиска?
    Я хочу чтобы поиск срабатывал при вводе 3 символов и больше.

    Andrew 3.3 года назад

    добавьте атрибут minlength="3" к полю ввода

    lethalblo 3.3 года назад

    у меня поле общее для поиска записей и поиска такс, на одной страницы выдает результаты. Выдачу записей хотелось бы оставить как есть.

    Andrew 3.3 года назад

    у меня поле общее для поиска записей и поиска такс, на одной страницы выдает результаты. Выдачу записей хотелось бы оставить как есть.

    и каким образом атрибут, на который обращает внимание только браузер, помешает поиску?

    lethalblo 3.3 года назад

    Хотелось бы чтобы поиск срабатывал как и раньше, но результаты по актерам отображались с введенным минимальным количеством символов.
    при добавлении атрибута искать записи уже не получиться

    Andrew 3.3 года назад

    обрезаете значение поисковой строки до нужного размера функцией mb_substr() и отправляете в запрос(ы), которыми получаете результаты поиска

    lethalblo 3.3 года назад

    Сейчас через обычную форму поиска передаю поисковый запрос и получаю результат, но если в конце запроса к примеру поставить пробел, то ничего уже не находит. Можно как-то сделать, чтобы лишние пробелы не учитывались?

    Andrew 3.3 года назад

    универсальная, имеющаяся во всех современных языках, функция trim() обрезает пробелы и спецсимволы с обоих краев переданной строки. Если нужно, чтобы строка обрезалась только с одной стороны, используйте PHP-функции ltrim() для обрезки с начала строки и rtrim() - с конца.

    lethalblo 3.3 года назад

    а если между словами 2 пробела? лишний можно убрать?

    Andrew 3.2 года назад

    а если между словами 2 пробела? лишний можно убрать?

    $string = preg_replace('/[\s]{2,}/gm', ' ', $string);
    lethalblo 3.2 года назад

    Не совсем понятно куда встраивать эту строку

    Комментировать
На вопросы могут отвечать только зарегистрированные пользователи. Вход . Регистрация