✅ Новости WEB и WordPress, темы, плагины. Здесь мы делимся советами и лучшими решениями для веб-сайтов.

Как создать собственный шаблон расширенного поиска в WordPress

64

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

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

Что мы будем делать

Мы создадим собственный тип записи для книг и привязанную к ней пользовательскую иерархическую таксономию для жанра. Кроме того, каждая книга имеет настраиваемые поля для автора (авторов), года публикации, номера ISBN и флажка, следует ли включать книги, которых нет в наличии. Что касается самой страницы поиска, мы создадим шаблон страницы, в котором будет находиться большая часть нашего кода. Страница начнется с отображения пользовательской формы в начале; показ всех возможных параметров для фильтрации результатов. Под ним все результаты книг появятся в списке. Мы определяем количество результатов на странице и добавляем нумерацию страниц внизу, если это число превышает это значение.

Это возможные параметры фильтра, которые мы создадим для нашего шаблона расширенного поиска:

  • Ввод текста для поиска любой строки в заголовке и содержимом поста.
  • Выпадающий список для выбора жанра. Позволяет выбрать термин или оставить значение «Любой».
  • Вход для ввода имени автора, который ищет в пользовательской мета. При слабом совпадении, что означает ввод «Отметить», будут возвращены все авторы, чье имя содержит или содержит «Отметить».
  • Ввод числа для ввода года публикации книги, которая выполняет поиск в пользовательской мета. Неточное соответствие означает, что ввод, например, «20» будет соответствовать любой книге, опубликованной в 1920 году, или любому году, начинающемуся с 20.
  • Вход для ввода ISBN (международный идентификатор книги ), который выполняет поиск в пользовательской мета. Возвращает только точные совпадения.
  • Отметьте, следует ли включать книги, которых нет в наличии, еще одна пользовательская мета. По умолчанию этот флажок не установлен, что означает, что в результатах отображаются только те книги, которые есть в наличии.

Форма настроена на использование метода GET, что означает, что любые искомые параметры будут добавлены к странице в URL-адресе в форме «?book-search=world&year-published=2016&book-author=mark«. Другой вариант, если вы хотите избежать «уродливых URL-адресов», — это использование Javascript и AJAX. Но есть некоторые недостатки с этим. Прежде всего, невозможно добавить в закладки поиск с определенными параметрами поиска, «предварительно заполненными». Представьте, что вы где-то на своем сайте хотите сделать прямую ссылку на страницу пользовательского поиска определенного автора. Затем вы можете сделать так, чтобы ссылка вела на вашу страницу поиска, добавляя " ?author=mark", и, таким образом, щелчок по ссылке приведет непосредственно к результатам для этого автора. Этого невозможно добиться с помощью AJAX.

Параметры поиска являются взаимодополняющими. Это означает, что при объединении, например, года «2011» и автора «Какой-то парень» будут возвращены только книги, соответствующие ОБОИМ этим параметрам. Если мы также укажем «смешно» в текстовом вводе общего поиска, мы получим только те результаты, которые соответствуют всем трем критериям. Сказано другими словами; мы будем использовать логику И. Это наиболее распространенный метод фильтрации результатов поиска.

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

Как создать собственный шаблон расширенного поиска в WordPress

Примечание о разбиении на страницы с пользовательским запросом

Если вы хотите разбивать на страницы пользовательский запрос на одной странице, нужно знать несколько вещей. Разбиение запроса на страницы может быть сгенерировано с помощью функций WordPress [the_posts_pagination](https://developer.wordpress.org/reference/functions/the_posts_pagination/)(), [paginate_links](https://developer.wordpress.org/reference/functions/paginate_links/)()или двух [next_post_link](https://developer.wordpress.org/reference/functions/next_post_link/)()и [previous_post_link](https://developer.wordpress.org/reference/functions/previous_post_link/)(). Однако они закодированы для работы с глобальным wp_queryобъектом (который для шаблона страницы является самой страницей), а не с пользовательским запросом.

Есть несколько обходных путей, таких как самостоятельное написание функции разбивки на страницы. Или вы можете использовать действие pre_get_postsи манипулировать wp_queryобъектом. К сожалению, этот метод слишком поздно влияет на функции разбиения на страницы. Другой вариант — полностью пропустить разбиение на страницы и просто показать все сообщения. Это может быть вариантом, если у вас не так много сообщений, но если вы создаете шаблон расширенного пользовательского поиска — я предполагаю, что у вас довольно много сообщений.

То, что мы будем делать в этом руководстве, является своего рода «хакерским» методом. В шаблоне страницы мы переопределим wp_queryобъект с помощью нашего пользовательского запроса, чтобы функции цикла и разбивки на страницы работали должным образом. С этим методом я добился наибольшего успеха.

Без лишних слов, давайте начнем кодировать!

Настройка пользовательского типа поста, таксономии и мета-полей

Первым шагом является определение пользовательского типа сообщения, для которого мы хотим создать шаблон расширенного поиска. Если вы уже настроили пользовательский тип записи или хотите реализовать его для записей или страниц, вы можете сразу перейти к следующей части.

Мы определяем пользовательский тип записи bookс иерархической пользовательской таксономией book_category. Я не буду вдаваться в подробности, объясняя, как создавать пользовательские типы записей и таксономии здесь. Если вам интересно узнать больше, у меня есть пост, в котором подробно рассказывается об этом.

Поместите этот код в любое место в коде вашей темы functions.phpили плагина:

add_action('init', function() {
    register_post_type('book', [
        'label' => __('Books', 'txtdomain'),
        'public' => true,
        'menu_position' => 5,
        'menu_icon' => 'dashicons-book',
        'supports' => ['title', 'editor', 'thumbnail', 'author', 'revisions', 'comments'],
        'show_in_rest' => true,
        'rewrite' => ['slug' => 'book'],
        'taxonomies' => ['book_category'],
        'labels' => [
            'singular_name' => __('Book', 'txtdomain'),
            'add_new_item' => __('Add new book', 'txtdomain'),
            'new_item' => __('New book', 'txtdomain'),
            'view_item' => __('View book', 'txtdomain'),
            'not_found' => __('No books found', 'txtdomain'),
            'not_found_in_trash' => __('No books found in trash', 'txtdomain'),
            'all_items' => __('All books', 'txtdomain'),
            'insert_into_item' => __('Insert into book', 'txtdomain')
        ],
    ]);
 
    register_taxonomy('book_category', ['book'], [
        'label' => __('Book Category', 'txtdomain'),
        'hierarchical' => true,
        'rewrite' => ['slug' => 'book-category'],
        'show_admin_column' => true,
        'show_in_rest' => true,
        'labels' => [
            'singular_name' => __('Book Category', 'txtdomain'),
            'all_items' => __('All Book Categories', 'txtdomain'),
            'edit_item' => __('Edit Book Category', 'txtdomain'),
            'view_item' => __('View Book Category', 'txtdomain'),
            'update_item' => __('Update Book Category', 'txtdomain'),
            'add_new_item' => __('Add New Book Category', 'txtdomain'),
            'new_item_name' => __('New Book Category Name', 'txtdomain'),
            'search_items' => __('Search Book Categories', 'txtdomain'),
            'parent_item' => __('Parent Book Category', 'txtdomain'),
            'parent_item_colon' => __('Parent Book Category:', 'txtdomain'),
            'not_found' => __('No Book Categories found', 'txtdomain'),
        ]
    ]);
});

Это приведет к созданию пользовательского типа сообщения с прикрепленной к нему таксономией в админке.

Настройка пользовательских метаданных постов зависит от вас — либо вручную, [add_meta_box](https://developer.wordpress.org/reference/functions/add_meta_box/)()либо с помощью плагина Advanced Custom Fields (ACF), который идеально подходит для такой работы. Я буду использовать ACF для программной настройки полей, например:

if (function_exists('acf_add_local_field_group')) {
    add_action('acf/init', function() {
        $fields = [
            [
                'key' => 'field_author',
                'label' => __('Author(s)', 'txtdomain'),
                'name' => 'book_author',
                'type' => 'textarea',
                'rows' => 3,
                'new_lines' => 'wpautop',
            ],
            [
                'key' => 'field_year_published',
                'label' => __('Year published', 'txtdomain'),
                'name' => 'year_published',
                'type' => 'number',
            ],
            [
                'key' => 'field_isbn',
                'label' => __('ISBN', 'txtdomain'),
                'name' => 'isbn',
                'type' => 'text',
            ],
            [
                'key' => 'field_in_stock',
                'label' => __('Stock status', 'txtdomain'),
                'name' => 'in_stock',
                'type' => 'true_false',
                'message' => __('In stock', 'txtdomain'),
                'default_value' => 1,
            ],
        ];
 
        acf_add_local_field_group([
            'key' => 'group_book_fields',
            'title' => __('Book Details', 'txtdomain'),
            'fields' => $fields,
            'label_placement' => 'top',
            'menu_order' => 0,
            'style' => 'default',
            'position' => 'normal',
            'location' => [
                [
                    [
                        'param' => 'post_type',
                        'operator' => '==',
                        'value' => 'book'
                    ]
                ]
            ],
        ]);
    });
}

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

Обратите внимание на мета-имена; например book_author, year_publishedи так далее. Вы будете ссылаться на них, когда мы будем создавать пользовательский запрос в шаблоне расширенного поиска.

С плагином ACF и приведенным выше кодом редактирование одной книги будет выглядеть так:

Как создать собственный шаблон расширенного поиска в WordPress

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

Создание шаблона страницы

Давайте создадим шаблон страницы, в который мы поместим наш шаблон расширенного поиска. Сделайте копию вашей темы single.phpили page.phpи переименуйте ее, например, в template-booksearch.php. HTML-код зависит от вас, но причина, по которой мы делаем копию single или page, заключается в том, что они, вероятно, являются наиболее близким шаблоном с точки зрения макета.

В самом верху шаблона страницы мы указываем, что это шаблон страницы, написав «Имя шаблона» и его имя в блоке комментариев. Это позволит нам выбрать шаблон страницы при редактировании страницы.

<?php /* Template Name: Advanced Book Search */
get_header(); ?>
...

Разделы, которые нам нужно закодировать в нашем шаблоне, следующие, в этом порядке:

  1. Сохраните все переменные, ранее отправленные формой, используя get_query_var(). Также необходимо сохранить текущую страницу
  2. Визуализация формы поиска с кнопкой отправки для выполнения поиска
  3. Сбросить wp_queryобъект
  4. Настройте аргументы для нового WP_Query()в зависимости от искомых параметров и запустите запрос. Назначить пользовательский запрос wp_queryобъекту
  5. Прокрутите результаты и отобразите их. Также отображать ссылки на страницы
  6. Сбросить wp_queryобъект обратно к тому, что было

Причина, по которой нам нужно заранее сохранить все искомые переменные и текущую страницу, заключается в том, что эти переменные будут потеряны, как только мы сбросим wp_queryобъект на шаге 3. Нам также нужны переменные для нашей формы поиска, чтобы заполнить поля.

В вашем шаблоне определите место, где вы хотите вывести свой пользовательский поиск, и давайте начнем сверху:

1 Получить все искомые переменные

Мы получаем параметры GET (из URL) с помощью [get_query_var](https://developer.wordpress.org/reference/functions/get_query_var/)(). Например; если у нас есть параметр ?book-author=benjaminв URL-адресе, использование get_query_var('book-author')вернет строку ‘ benjamin‘. Извлечение всех переменных может быть выполнено следующим образом:

$search_string = get_query_var('book-search');
$author = get_query_var('book-author');
$category = get_query_var('book-category');
$year = get_query_var('year-published');
$isbn = get_query_var('isbn');
$out_of_stock = get_query_var('out-of-stock');

Но это все настраиваемые параметры, которые не являются частью стандартных GET-параметров WordPress. WordPress будет игнорировать неизвестные GET-параметры, поэтому их вызов всегда будет возвращать пустую строку. Нам нужно указать WordPress разрешить каждый из этих параметров GET. Мы делаем это путем фильтрации query_vars. В вашем functions.php, добавьте это также:

add_filter('query_vars', function($vars) {
    $vars[] = 'book-search';
    $vars[] = 'book-author';
    $vars[] = 'book-category';
    $vars[] = 'year-published';
    $vars[] = 'isbn';
    $vars[] = 'out-of-stock';
    return $vars;
});

Теперь наши get_query_var()должны иметь возможность получать параметры GET. Если они не установлены, возвращается пустая строка.

Нам также нужно получить текущую страницу, прежде чем мы испортим wp_queryобъект. Текущая страница — это скрытый параметр GET с именем paged. Мы получим его так же, как и другие наши параметры GET, но установим его по умолчанию равным 1, если он пуст.

$paged = (get_query_var('paged'))? get_query_var('paged'): 1;

Примечание. Поскольку pagedэто стандартный параметр WordPress, нам не нужно добавлять pagedего в query_varsфильтр.

2 Визуализация формы поиска

Форма поиска будет просто <form>с необходимыми входными данными и кнопкой отправки формы. HTML полностью зависит от вас, в приведенном ниже примере я добавляю входные данные в простой список. Я не буду включать какие-либо стили в этот урок, это зависит от вас. Вы можете выбрать стиль формы поиска, чтобы он располагался вверху результатов или сбоку — вертикально вниз вместе с результатами поиска.

Примечание. Чтобы сократить шаблон расширенного поиска и сделать его модульным, вы можете выделить часть формы поиска в отдельный файл шаблона и включить ее в файл [get_template_part](https://developer.wordpress.org/reference/functions/get_template_part/)(). Но для простоты этого урока я включу все в один файл шаблона.

Сама форма должна иметь метод GET, а действие должно указывать на страницу, на которой мы находимся. Для этого мы обращаемся к глобальному $postобъекту и получаем от него постоянную ссылку. В конце мы добавляем кнопку отправки, которая отправит форму.

global $post;
?>
<form method="GET" action="<?php echo get_permalink($post->ID); ?>">
    <ul class="book-search-form">
 
    </ul>
    <input type="submit" value="<?php _e('Search', 'txtdomain'); ?>" />
</form>
<?php

В неупорядоченном списке мы добавим подходящий ввод для каждого из наших возможных параметров поиска. Настройте HTML и параметры поиска в соответствии с вашими потребностями:

global $post;
?>
<form method="GET" action="<?php echo get_permalink($post->ID); ?>">
    <ul class="book-search-form">
        <li>
            <label for="book-search"><?php _e('Search...', 'txtdomain'); ?></label>
            <input type="text" id="book-search" name="book-search" value="<?php echo $search_string; ?>" />
        </li>
        <li>
            <label for="book-category"><?php _e('Genre', 'txtdomain'); ?></label>
            <?php 
            wp_dropdown_categories([
                'taxonomy' => 'book_category',
                'name' => 'book-category',
                'id' => 'book-category',
                'value_field' => 'slug',
                'selected' => $category,
                'show_option_none' => __('Any genre', 'txtdomain'),
                'option_none_value' => '',
                'hierarchical' => true,
                'hide_if_empty' => false,
            ]);
            ?>
        </li>
        <li>
            <label for="book-author"><?php _e('Author', 'txtdomain'); ?></label>
            <input type="text" id="book-author" name="book-author" value="<?php echo $author; ?>" />
        </li>
        <li>
            <label for="year-published"><?php _e('Year published', 'txtdomain'); ?></label>
            <input type="number" id="year-published" name="year-published" value="<?php echo $year; ?>" />
        </li>
        <li>
            <label for="isbn"><?php _e('ISBN', 'txtdomain'); ?></label>
            <input type="text" id="isbn" name="isbn" value="<?php echo $isbn; ?>" />
        </li>
        <li>
            <input type="checkbox" id="out-of-stock" name="out-of-stock" value="out-of-stock" <?php checked($out_of_stock, 'out-of-stock'); ?> /><label for="out-of-stock"><?php _e('Include out of stock', 'txtdomain'); ?></label>
        </li>
    </ul>
    <input type="submit" value="<?php _e('Search', 'txtdomain'); ?>" />
</form>
<?php

Обратите внимание на nameатрибуты; это то, что будет отображаться в URL-адресе при отправке формы. Они должны соответствовать query_varsи get_query_var()определены нами ранее!

Приведенный выше код начинается с рендеринга ввода текста для обычного текстового поиска. Мы устанавливаем valueранее найденную переменную, которую мы извлекли с помощью get_query_var(). Это гарантирует, что ввод не будет очищен после того, как мы выполнили поиск.

Следующий параметр — это раскрывающийся список жанров из нашей пользовательской таксономии. Чтобы отобразить это, мы используем функцию [wp_dropdown_categories](https://developer.wordpress.org/reference/functions/wp_dropdown_categories/)(). Взгляните на страницу документации, чтобы понять, почему мы добавляем все эти параметры, чтобы настроить раскрывающийся список в соответствии с нашими потребностями. Важно, чтобы была taxonomyустановлена ​​наша пользовательская таксономия, nameатрибут был правильным и selectedбыл установлен на значение ранее найденной переменной. Мы также устанавливаем значения терминов в качестве их слагов вместо идентификаторов терминов. ?book-category=fictionВместо ?book-category=42. _ Мы также активируем опцию «нет» для добавления опции «Любой жанр».

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

3 Сбросьте wp_query

Следующий шаг — небольшой хак, чтобы убедиться, что разбиение на страницы работает для нашего пользовательского запроса. Мы просто сохраняем текущий $wp_queryв некоторой переменной, а затем присваиваем ей значение null. Позже, на шаге 6, мы сбросим его из $tmp_wpqueryпеременной.

$tmp_wpquery = $wp_query;
$wp_query = null;

4 Настройте аргументы и запустите собственный запрос

Эта часть посвящена выполнению нового запроса. Мы начинаем с настройки самых основных аргументов, а затем условно добавляем параметры в зависимости от того, что было найдено в ранее искомых переменных (из наших get_query_var()s).

$args = [
    'post_type' => 'book',
    'posts_per_page' => 20,
    'paged' => $paged
];
 
$meta_query = [];
$tax_query = [];
 
if (!empty($search_string)) {
    $args['s'] = $search_string;
}
 
if (!empty($category)) {
    $tax_query[] = [
        'taxonomy' => 'book_category',
        'field' => 'slug',
        'terms' => $category
    ];
}
 
if (!empty($author)) {
    $meta_query[] = [
        'key' => 'book_author',
        'value' => $author,
        'compare' => 'LIKE'
    ];
}
 
if (!empty($year)) {
    $year = (int) $year;
    $meta_query[] = [
        'key' => 'year_published',
        'value' => $year,
        'compare' => 'LIKE'
    ];
}
 
if (!empty($isbn)) {
    $meta_query[] = [
        'key' => 'isbn',
        'value' => $isbn,
    ];
}
 
if (empty($out_of_stock)) {
    $meta_query[] = [
        'key' => 'in_stock',
        'value' => true,
    ];
}
 
if (!empty($meta_query)) {
    $args['meta_query'] = $meta_query;
}
if (!empty($tax_query)) {
    $args['tax_query'] = $tax_query;
}
 
// Perform query and assign it to wp_query
$books = new WP_Query($args);
$wp_query = $books;

Приведенный выше код в основном создает файл WP_Queryс параметрами. Страница документации для WP_Query— отличный ресурс для выяснения того, как построить запрос.

Самые первые аргументы гарантируют, что мы запрашиваем только книги и что мы правильно информируем о том, на какой странице мы находимся в данный момент, из pagedпеременной, которую мы извлекли ранее. Количество сообщений на странице зависит от вас, я просто установил его на 20.

Обратите внимание, что добавление ‘ compare‘ к ‘ LIKE‘ заставит WordPress искать все, что содержит данную строку. Я не добавлял это в поиск ISBN, потому что для этого поля я хочу, чтобы он находил идеально совпадающие результаты.

Важный момент — в самом конце, когда мы фактически выполняем запрос и присваиваем этот запрос wp_queryпеременной.

5 Прокрутите результаты запроса и отобразите разбивку на страницы.

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

В приведенном ниже коде показан базовый пример циклического просмотра результатов с вызовом get_template_part()каждого сообщения. После цикла the_posts_pagination()используется для отображения ссылок на страницы. Если запрос не вернул сообщений, отображается простой абзац с текстом.

if (have_posts()) { 
    while (have_posts()): the_post();
        get_template_part('content', 'book');
    endwhile;
 
    the_posts_pagination([
        'mid_size' => 2,
        'prev_text' => __('« Previous', 'txdomain'),
        'next_text' => __('Next »', 'txdomain')
    ]);
} else {
    ?><p class="no-posts"><?php _e('No books found.', 'txdomain'); ?></p><?php
}

Настройте HTML и вывод в соответствии с вашими потребностями. Приведенный выше код ожидает файл шаблона в теме с именем content-book.phpдля рендеринга одной книги в цикле. Я не буду показывать вам, как отображать каждое сообщение, так как это то, что вы, скорее всего, уже контролируете.

6 Сбросьте wp_query обратно к тому, что было

Последним шагом является сброс wp_queryобъекта к тому, что мы сохранили ранее на шаге 3. Мы устанавливаем его nullпервым, чтобы гарантировать его сброс.

$wp_query = null;
$wp_query = $tmp_wpquery;

Заключение и окончательный результат

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

С некоторыми базовыми стилями это может легко выглядеть примерно так:

Как создать собственный шаблон расширенного поиска в WordPress

Вот окончательный код; functions.phpдеталь и шаблон :

// Custom post type for books and custom taxonomy
add_action('init', function() {
    register_post_type('book', [
        'label' => __('Books', 'txtdomain'),
        'public' => true,
        'menu_position' => 5,
        'menu_icon' => 'dashicons-book',
        'supports' => ['title', 'editor', 'thumbnail', 'author', 'revisions', 'comments'],
        'show_in_rest' => true,
        'rewrite' => ['slug' => 'book'],
        'taxonomies' => ['book_category'],
        'labels' => [
            'singular_name' => __('Book', 'txtdomain'),
            'add_new_item' => __('Add new book', 'txtdomain'),
            'new_item' => __('New book', 'txtdomain'),
            'view_item' => __('View book', 'txtdomain'),
            'not_found' => __('No books found', 'txtdomain'),
            'not_found_in_trash' => __('No books found in trash', 'txtdomain'),
            'all_items' => __('All books', 'txtdomain'),
            'insert_into_item' => __('Insert into book', 'txtdomain')
        ],
    ]);
 
    register_taxonomy('book_category', ['book'], [
        'label' => __('Book Category', 'txtdomain'),
        'hierarchical' => true,
        'rewrite' => ['slug' => 'book-category'],
        'show_admin_column' => true,
        'show_in_rest' => true,
        'labels' => [
            'singular_name' => __('Book Category', 'txtdomain'),
            'all_items' => __('All Book Categories', 'txtdomain'),
            'edit_item' => __('Edit Book Category', 'txtdomain'),
            'view_item' => __('View Book Category', 'txtdomain'),
            'update_item' => __('Update Book Category', 'txtdomain'),
            'add_new_item' => __('Add New Book Category', 'txtdomain'),
            'new_item_name' => __('New Book Category Name', 'txtdomain'),
            'search_items' => __('Search Book Categories', 'txtdomain'),
            'parent_item' => __('Parent Book Category', 'txtdomain'),
            'parent_item_colon' => __('Parent Book Category:', 'txtdomain'),
            'not_found' => __('No Book Categories found', 'txtdomain'),
        ]
    ]);
});
 
// ACF for custom meta fields
if (function_exists('acf_add_local_field_group')) {
    add_action('acf/init', function() {
        $fields = [
            [
                'key' => 'field_author',
                'label' => __('Author(s)', 'txtdomain'),
                'name' => 'book_author',
                'type' => 'textarea',
                'rows' => 3,
                'new_lines' => 'wpautop',
            ],
            [
                'key' => 'field_year_published',
                'label' => __('Year published', 'txtdomain'),
                'name' => 'year_published',
                'type' => 'number',
            ],
            [
                'key' => 'field_isbn',
                'label' => __('ISBN', 'txtdomain'),
                'name' => 'isbn',
                'type' => 'text',
            ],
            [
                'key' => 'field_in_stock',
                'label' => __('Stock status', 'txtdomain'),
                'name' => 'in_stock',
                'type' => 'true_false',
                'message' => __('In stock', 'txtdomain'),
                'default_value' => 1,
            ],
        ];
 
        acf_add_local_field_group([
            'key' => 'group_book_fields',
            'title' => __('Book Details', 'txtdomain'),
            'fields' => $fields,
            'label_placement' => 'top',
            'menu_order' => 0,
            'style' => 'default',
            'position' => 'normal',
            'location' => [
                [
                    [
                        'param' => 'post_type',
                        'operator' => '==',
                        'value' => 'book'
                    ]
                ]
            ],
        ]);
    });
}
 
// Allow custom GET parameters
add_filter('query_vars', function($vars) {
    $vars[] = 'book-search';
    $vars[] = 'book-author';
    $vars[] = 'book-category';
    $vars[] = 'year-published';
    $vars[] = 'isbn';
    $vars[] = 'out-of-stock';
    return $vars;
});
<?php 
/* Template Name: Advanced Book Search */
get_header(); ?>
 
<main class="content">
    <?php 
 
    // Store variables
    $paged = (get_query_var('paged'))? get_query_var('paged'): 1;
    $search_string = get_query_var('book-search');
    $author = get_query_var('book-author');
    $category = get_query_var('book-category');
    $year = get_query_var('year-published');
    $isbn = get_query_var('isbn');
    $out_of_stock = get_query_var('out-of-stock');
 
    // Search form
    global $post;
    ?><form method="GET" action="<?php echo get_permalink($post->ID); ?>">
        <ul class="book-search-form">
            <li>
                <label for="book-search"><?php _e('Search...', 'txtdomain'); ?></label>
                <input type="text" id="book-search" name="book-search" value="<?php echo $search_string; ?>" />
            </li>
            <li>
                <label for="book-category"><?php _e('Genre', 'txtdomain'); ?></label>
                <?php 
                wp_dropdown_categories([
                    'taxonomy' => 'book_category',
                    'name' => 'book-category',
                    'id' => 'book-category',
                    'value_field' => 'slug',
                    'selected' => $category,
                    'show_option_none' => __('Any genre', 'txtdomain'),
                    'option_none_value' => '',
                    'hierarchical' => true,
                    'hide_if_empty' => false,
                ]);
                ?>
            </li>
            <li>
                <label for="book-author"><?php _e('Author', 'txtdomain'); ?></label>
                <input type="text" id="book-author" name="book-author" value="<?php echo $author; ?>" />
            </li>
            <li>
                <label for="year-published"><?php _e('Year published', 'txtdomain'); ?></label>
                <input type="number" id="year-published" name="year-published" value="<?php echo $year; ?>" />
            </li>
            <li>
                <label for="isbn"><?php _e('ISBN', 'txtdomain'); ?></label>
                <input type="text" id="isbn" name="isbn" value="<?php echo $isbn; ?>" />
            </li>
            <li>
                <input type="checkbox" id="out-of-stock" name="out-of-stock" value="out-of-stock" <?php checked($out_of_stock, 'out-of-stock'); ?> /><label for="out-of-stock"><?php _e('Include out of stock', 'txtdomain'); ?></label>
            </li>
        </ul>
        <input type="submit" value="<?php _e('Search', 'txtdomain'); ?>" />
    </form>
    <?php
 
    // Reset wp_query temporary
    $tmp_wpquery = $wp_query;
    $wp_query = null;
 
    // Start setting up custom query
    $args = [
        'post_type' => 'book',
        'posts_per_page' => 20,
        'paged' => $paged
    ];
 
    $meta_query = [];
    $tax_query = [];
 
    // Search post title and content
    if (!empty($search_string)) {
        $args['s'] = $search_string;
    }
 
    // Search by category
    if (!empty($category)) {
        $tax_query[] = [
            'taxonomy' => 'book_category',
            'field' => 'slug',
            'terms' => $category
        ];
    }
 
    // Search by ISBN
    if (!empty($author)) {
        $meta_query[] = [
            'key' => 'book_author',
            'value' => $author,
            'compare' => 'LIKE'
        ];
    }
 
    // Search by year
    if (!empty($year)) {
        $year = (int) $year;
        $meta_query[] = [
            'key' => 'year_published',
            'value' => $year,
            'compare' => 'LIKE'
        ];
    }
 
    // Search by ISBN
    if (!empty($isbn)) {
        $meta_query[] = [
            'key' => 'isbn',
            'value' => $isbn,
        ];
    }
 
    // Filter out of stock
    if (empty($out_of_stock)) {
        $meta_query[] = [
            'key' => 'in_stock',
            'value' => true,
        ];
    }
 
    // Add to query arguments
    if (!empty($meta_query)) {
        $args['meta_query'] = $meta_query;
    }
    if (!empty($tax_query)) {
        $args['tax_query'] = $tax_query;
    }
 
    // Perform query and assign it to wp_query
    $books = new WP_Query($args);
    $wp_query = $books;
 
    // Loop through results
    if (have_posts()) { 
        while (have_posts()): the_post();
            get_template_part('content', 'book');
        endwhile;
 
        the_posts_pagination([
            'mid_size' => 2,
            'prev_text' => __('« Previous', 'txdomain'),
            'next_text' => __('Next »', 'txdomain')
        ]);
    } else {
        ?><p class="no-posts"><?php _e('No books found.', 'txdomain'); ?></p><?php
    }
 
    // Reset wp_query back to what it was
    $wp_query = null;
    $wp_query = $tmp_wpquery;
    ?>
</main>
<?php get_footer(); ?>

Источник записи: awhitepixel.com

Этот веб-сайт использует файлы cookie для улучшения вашего опыта. Мы предполагаем, что вы согласны с этим, но вы можете отказаться, если хотите. Принимаю Подробнее