Как создать пользовательский поиск для произвольного типа записей?

7 мар. 2013 г., 23:56:29
Просмотры: 242K
Голосов: 55

У меня есть поле поиска для записей блога, но мне нужно другое для произвольного типа записей. Как создать эту пользовательскую форму поиска с другим макетом результатов поиска?

1
Комментарии

В случае поиска для WooCommerce (тип записи товара), просто скопируйте файл woocommerce/templates/archive-product.php в вашу дочернюю тему и затем настройте его... 1 час на это!! :(

gtamborero gtamborero
2 дек. 2020 г. 13:19:05
Все ответы на вопрос 8
7
79

Вот что я попробовал и получил решение в 3 шага. Допустим, ваш произвольный тип записи - "products"

1. Добавьте код функции, здесь вы можете указать archive-search.php

function template_chooser($template)   
{    
  global $wp_query;   
  $post_type = get_query_var('post_type');   
  if( $wp_query->is_search && $post_type == 'products' )   
  {
    return locate_template('archive-search.php');  //  перенаправление на archive-search.php
  }   
  return $template;   
}
add_filter('template_include', 'template_chooser');    

2. Создайте шаблон результатов поиска для произвольного типа записи (archive-search.php)

        <?php
        /* Template Name: Custom Search */        
        get_header(); ?>             
        <div class="contentarea">
            <div id="content" class="content_right">  
                     <h3>Результаты поиска для: <?php echo htmlentities($s, ENT_QUOTES, 'UTF-8'); ?> </h3>       
                     <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>    
                <div id="post-<?php the_ID(); ?>" class="posts">        
                     <article>        
                    <h4><a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h4>        
                    <p><?php the_excerpt(); ?></p>        
                    <p align="right"><a href="<?php the_permalink(); ?>">Читать далее</a></p>    
                    <span class="post-meta"> Автор: <?php the_author(); ?>    
                     | Дата: <?php echo date('j F Y'); ?></span>    

                    </article><!-- #post -->    
                </div>
        <?php endwhile; ?>
    <?php endif; ?>




           </div><!-- content -->    
        </div><!-- contentarea -->   
        <?php get_sidebar(); ?>
        <?php get_footer(); ?>
 
  1. Создайте форму поиска
    В этой форме поиска значение "products" скрыто, и поиск будет выполняться только по записям типа products.

     <div>   
        <h3>Поиск товаров</h3>
        <form role="search" action="<?php echo site_url('/'); ?>" method="get" id="searchform">
        <input type="text" name="s" placeholder="Поиск товаров"/>
        <input type="hidden" name="post_type" value="products" /> <!-- // скрытое значение 'products' -->
        <input type="submit" alt="Поиск" value="Поиск" />
      </form>
     </div>
    

для получения дополнительной информации рекомендую перейти по ссылке
http://www.wpbeginner.com/wp-tutorials/how-to-create-advanced-search-form-in-wordpress-for-custom-post-types/

8 мар. 2013 г. 11:04:14
Комментарии

Совет: при регистрации типа записи аргумент publicly_queryable должен быть установлен как true. В противном случае get_query_var('post_type') никогда не вернет значение post_type, указанное в аргументе url. https://codex.wordpress.org/Function_Reference/register_post_type#Arguments

Gustavo Daniel Gustavo Daniel
21 мая 2015 г. 20:46:45

Еще один совет/предлагаемое изменение: get_query_var('post_type') возвращал массив (а не строку), поэтому не мог сравниваться напрямую. Поскольку я ищу только один тип записи за раз, я просто изменил переменную $post_type на $post_type[0].

indextwo indextwo
8 апр. 2016 г. 18:51:24

есть ли способ переписать URL с http://localhost:3000/?s=cloud%27&post_type=product на http://localhost:3000/search/cloud/product

YarGnawh YarGnawh
6 нояб. 2017 г. 18:33:07

@YarGnawh Извините за поздний ответ, посмотрите это https://wordpress.stackexchange.com/questions/15418/pretty-permalinks-for-search-results-with-extra-query-var. Также есть плагин для перезаписи https://wordpress.org/plugins/rewrite/

Ronald Ronald
13 нояб. 2017 г. 13:20:43

фильтр search_template кажется более подходящей альтернативой для template_include

Alexey Kosov Alexey Kosov
19 июл. 2018 г. 16:02:55

Приведенный выше код сработал для меня. Мне просто нужно было отредактировать <?php the_exerpt(); ?> и изменить его на <?php the_excerpt(); ?>

Cypher Cypher
2 февр. 2021 г. 06:02:43

Для ответа, написанного 9 лет назад, я могу подтвердить в 2022 году, что он до сих пор работает и с отличной точностью! Превосходная работа @Ronald, вы удивительны!

Periklis Kakarakidis Periklis Kakarakidis
5 мар. 2022 г. 12:24:01
Показать остальные 2 комментариев
0

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

Форма поиска для произвольного типа записей:

<form role="search" method="get" class="search-form" action="<?php echo home_url( '/' ); ?>">
    <label>
        <span class="screen-reader-text"><?php echo _x( 'Искать:', 'label' ) ?></span>
        <input type="search" class="search-field" placeholder="<?php echo esc_attr_x( 'Поиск …', 'placeholder' ) ?>" value="<?php echo get_search_query() ?>" name="s" title="<?php echo esc_attr_x( 'Искать:', 'label' ) ?>" />
        <input type="hidden" name="post_type" value="book" />
    </label>
    <input type="submit" class="search-submit" value="<?php echo esc_attr_x( 'Поиск', 'submit button' ) ?>" />
</form>

В файле functions.php:

function searchfilter($query) {
    if ($query->is_search && !is_admin() ) {
        if(isset($_GET['post_type'])) {
            $type = $_GET['post_type'];
                if($type == 'book') {
                    $query->set('post_type',array('book'));
                }
        }       
    }
return $query;
}
add_filter('pre_get_posts','searchfilter');

В файле search.php:

<?php if (have_posts()) : ?>
<?php while (have_posts()) : the_post(); ?>
    <?php if(isset($_GET['post_type'])) {
        $type = $_GET['post_type'];
           if($type == 'book') {?>

               /* Формат для произвольного типа записей "book" */

           <?php } else { ?>

               /* Формат для произвольных типов записей, которые не являются "book",
               или вы можете использовать elseif для указания второго типа записи
               таким же образом, как выше. Скопируйте формат по умолчанию сюда, если у вас
               только один произвольный тип записи. */

           <?php } ?>
    <?php } else { ?>

              /* Формат для отображения, когда параметр post_type
              не установлен (т.е. формат по умолчанию) */
<?php } ?>
<?php endwhile; else: ?>

/* Что отображать, если результатов нет. */

<?php endif; ?>

Естественно, во всех трех местах вам нужно заменить "book" на ваш произвольный тип записи.

Надеюсь, это кому-нибудь поможет!

12 янв. 2016 г. 23:46:15
0

Более актуальный короткий код

function template_chooser($template)   
{    
  global $wp_query; 
  $post_type = $wp_query->query_vars["pagename"];   
  if( isset($_GET['s']) && $post_type == 'products' )   
  {

    return locate_template('archive-search.php');  // перенаправление на archive-search.php
  }   
  return $template;   
}
add_filter('template_include', 'template_chooser'); 
16 нояб. 2015 г. 06:18:12
1

Я искал возможность использовать две разные формы для обычного поиска и поиска по пользовательскому типу записей.

Мой пользовательский тип записей использует другой заголовок, чем обычные страницы. На обычной странице вызов моей формы поиска выглядит так:

<?php get_search_form(true); ?>

А вызов формы поиска в заголовке пользовательского типа записей выглядит так:

<?php get_template_part('search','library'); ?>

Которая имеет дополнительное поле:

<input type="hidden" name="post_type" value="library" /> //Где "library" - это мой пользовательский тип записей.

В файле functions.php у меня есть следующий код, который вы предоставили.

/** Пользовательский поиск для библиотеки */
function search_library($template)   
{    
  global $wp_query;   
  $post_type = get_query_var('post_type');   
  if( $wp_query->is_search && $post_type == 'library' )   
  {
    return locate_template('search-library.php');  // перенаправление на archive-search.php
  }   
  return $template;   
}
add_filter('template_include', 'search_library');

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

Редактирование: исправлен вызов функции get_search_form(), которая возвращала бы true в любом случае.

2 мар. 2017 г. 09:20:17
Комментарии

Стоит отметить, что get_search_form('true') должно быть get_search_form(true). Функция get_search_form ожидает булево значение на входе, то есть либо true, либо false. Заключая значение в кавычки, вы передаете строку, а не булев параметр. По тому, как устроена эта функция, оба варианта 'true' и 'false' вернут один и тот же результат, потому что они оба являются непустыми строками (что приводит к тому, что функция возвращает true в обоих случаях).

Mike Mike
22 февр. 2018 г. 03:29:40
1

Чтобы исправить проблему с пустым поиском, вы можете заменить код функции на следующий:

function template_chooser($template)   
{    
 global $wp_query;   
 $post_type = get_query_var('post_type');   
 if( isset($_GET['s']) && $post_type == 'products' )   
 {
  return locate_template('archive-search.php');  // перенаправление на archive-search.php
 }   
 return $template;   
}
add_filter('template_include', 'template_chooser');
16 сент. 2014 г. 13:33:32
Комментарии

Было бы здорово, если бы вы объяснили, как работает ваш код и раскрыли его источник

Pieter Goosen Pieter Goosen
16 сент. 2014 г. 14:00:22
2

У меня есть 10 произвольных типов записей (CPT), каждый со своей собственной страницей результатов поиска (с разными макетами), и стандартный подход не работал для меня.

После дополнительного исследования я нашел этот подход, где вы настраиваете шаблон search.php для загрузки другого шаблона, если в URL присутствует CPT.

По сути, в search.php нужно вставить следующее:

<?php

// проверяем, есть ли тип записи в URL + nonce для безопасности
if ( isset( $_GET['post_type'], $_GET['custom_search_nonce_field'] ) && wp_verify_nonce( $_GET['custom_search_nonce_field'], 'custom_search_nonce_action' ) ) {

// сохраняем для дальнейшего использования
$post_type = $_GET['post_type'];

// проверяем, существует ли шаблон поиска
if ( locate_template( 'search-' . $post_type . '.php' ) ) {
    // загружаем его и выходим
    get_template_part( 'search', $post_type );
    exit;
}

}

?>

а форма поиска будет выглядеть примерно так:

<form class="search" action="<?php echo home_url( '/' ); ?>">
  <input type="search" name="s" placeholder="Поиск&hellip;">
  <input type="submit" value="Искать">
  <input type="hidden" name="post_type" value="kb_article">
<?php wp_nonce_field( 'custom_search_nonce_action', 'custom_search_nonce_field' ); ?>
</form>
2 февр. 2021 г. 18:01:37
Комментарии

Должна ли здесь быть проверка nonce?

Adrian B Adrian B
4 окт. 2023 г. 14:23:53

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

RwkY RwkY
23 февр. 2024 г. 19:32:30
0

Я знаю, что это старая тема, но я использую пользовательские шорткоды в файле functions.php, чтобы включить поиск, привязанный к определенным типам записей и, в моем случае, пользовательским таксономиям. Я использую Pods для архива видеолекций по годам и хотел, чтобы поиск осуществлялся только в пределах этого года. Это сейчас работает (в моем файле functions.php):

/*Пользовательский поиск для Видео Архива 2020 года - добавляет шорткод [2020search] для поиска*/
function video2020searchform( $form ) {

    $form = '<form role="search" method="get" id="searchform" action="' . home_url( '/' ) . '" >
    <div class="my-custom-search"><label class="screen-reader-text" for="s">' . __('Поиск:') . '</label>
    <input type="hidden" name="video_year" value="video-archive-2020" />
    <input type="text" value="' . get_search_query() . '" name="s" id="s" placeholder="Поиск в архивах 2020 года по спикеру или ключевому слову..." />
    <input type="submit" id="searchsubmit" value="'. esc_attr__('Поиск') .'" />
    </div>
    </form>';

    return $form;
}

add_shortcode('2020search', 'video2020searchform');
// конец формы поиска 2020 года.   

Затем у меня есть страница с избранными видео за 2020 год, с шорткодом формы поиска над ней, чтобы пользователи могли искать остальные материалы за 2020 год. name="video_year" - это пользовательская таксономия, созданная с помощью Pods, тип записи также создан с помощью Pods и называется "videos", а value="video-archive-2020" - это ярлык из года видео Pods, который мне нужен. Если у вас есть пользовательский тип записи "books", таксономия "book-genre" и вы пытаетесь ограничить поиск категорией "adventure", то "book-genre" будет значением 'name', а "adventure" будет значением 'value'. Надеюсь, это кому-то поможет, и спасибо всем за предыдущие ответы!

14 июл. 2021 г. 15:39:51
0

В моем случае поиск работал отлично. Мне просто нужно было отфильтровать запрос, чтобы искать только среди типов записей курсов Learndash. Вот что я сделал:

// Фильтрует поисковый запрос, чтобы включать только тип записи 'sfwd-courses'
function fn_search_courses_only($query) {
    if( $query->is_search && ! is_admin() ) {
        $query->set( 'post_type', 'sfwd-courses' );
    }
}
add_action( 'pre_get_posts', 'fn_search_courses_only' );
18 нояб. 2024 г. 08:59:04