Пользовательский поиск: Искать записи, но отображать родительскую страницу в результатах

Вопрос или проблема

Я использую WordPress 3.5.1 с модифицированной темой twentytwelve.
Структура моего основного сайта основана на плагине Smooth Slider (jQuery Cycle).

У меня есть Страницы, которые содержат только шорткод (например, [smoothslider id='4']), чтобы отображать Записи, назначенные слайдеру. Когда я выполняю поиск на сайте, он возвращает результаты только для отдельных записей (и не для страниц, конечно). Это не то, что я хочу, так как слайдера больше нет. Эти записи не должны отображаться по отдельности.

Что я хотел бы сделать, так это вместо получения результатов с линками на отдельные записи, получить ссылки на родительскую страницу. Но у записей нет родителей, поэтому нужно взять это из menu_order (?) и установить результаты на эти URL.


Пример

МЕНЮ:

  • Машина [Страница – Перенаправление на первого ребенка: car-1]
    • car-1 [Страница – Содержимое: шорткод с “sliderid=1”]
      • car-1a [Запись – прикрепленная к sliderid=1 – Содержимое: текст+изображение]
      • car-1b [Запись – прикрепленная к sliderid=1 – Содержимое: текст+изображение]
      • car-1c [Запись – прикрепленная к sliderid=1 – Содержимое: текст+изображение]
    • car 2 [Страница – Содержимое: шорткод с “sliderid=2”]
      • car-2a [Запись – прикрепленная к sliderid=2 – Содержимое: текст+изображение]
      • car-2b [Запись – прикрепленная к sliderid=2 – Содержимое: текст+изображение]

Результаты поиска по запросу “машина”:

  • Результаты, которые я получаю:
    • example.com/car-1a,
    • example.com/car-1b,
    • example.com/car-2a
    • и т.д.
  • Результаты, которые я хочу:
    • example.com/CAR/car-1,
    • example.com/CAR/car-2,
    • и т.д.

Хорошо, я это понял; добавил следующее в functions.php:

add_filter( 'posts_request', 'my_request_filter', 10, 2 );

function my_request_filter($sql, $query) {
    if($query->is_main_query() && is_search()) {
        $sql = "SELECT * FROM wp_posts WHERE post_content LIKE '[smoothslider%' AND post_parent !='0'";
    }
    return $sql;
}

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

У меня не установлен ваш слайдер, поэтому я не могу это протестировать, но что-то вроде следующего – это то, что вам нужно:

function get_parent_page() {
  if (is_singular()) {
    global $wpdb,$post;
    if (isset($post->ID)) {
      $slide = $wpdb->get_var("SELECT DISTINCT slide_id FROM {$wpdb->prefix}smooth_slider WHERE post_id = {$post->ID} LIMIT 1");
      if (!empty($parent)) {
        $parent = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_status="publish" AND post_type="post" AND post_content LIKE \"%[smoothslider id='".$slide."']%\"");
        if (!empty($parent)) {
           wp_safe_redirect(get_permalink($parent));
        }
      }
    }
  }
}
add_action('template_redirect','get_parent_page');

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

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

Другой вариант – изменить ваш файл search.php (или создать его) так, чтобы постоянные ссылки указывали на родительскую запись. Вы могли бы использовать почти ту же функцию, просто передав ID записи.

function get_parent_page_permalink($postid) {
  global $wpdb;
  if (isset($postid)) {
    $slide = $wpdb->get_var("SELECT DISTINCT slide_id FROM {$wpdb->prefix}smooth_slider WHERE post_id = {$postid} LIMIT 1");
    if (!empty($parent)) {
      $parent = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_status="publish" AND post_type="post" AND post_content LIKE \"%[smoothslider id='".$slide."']%\"");
      if (!empty($parent)) {
         return get_permalink($parent);
      }
    }
  }
}

Это создаст еще большую нагрузку на сервер. У вас будет два дополнительных запроса для каждого результата в поиске, и, я верю, еще один запрос для каждого get_permalink.

Ответ или решение

Настройка поиска в WordPress: Отображение родительских страниц в результатах поиска

При использовании WordPress 3.5.1 и изменённой темы Twenty Twelve, ваша задача заключается в том, чтобы осуществлять поиск по постам, но отображать родительские страницы в результатах. Данная проблема основной — это некорректное поведение стандартного механизма поиска WordPress, который возвращает только отдельные посты вместо страниц, содержащих слайдеры. Мы определим несколько шагов для решения данной задачи.

Проблема

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

Решение

Для достижения желаемого результата можно воспользоваться фильтрацией запросов с помощью add_filter в файле functions.php. Необходимо настроить SQL-запрос таким образом, чтобы он возвращал страницы с определёнными шорткодами. Ниже представим более детальную реализацию.

Код для functions.php

add_filter('posts_search', 'custom_search_filter', 10, 2);
function custom_search_filter($search, $wp_query) {
    global $wpdb;

    // Проверяем, что это основной запрос и выполняется поиск
    if ($wp_query->is_main_query() && $wp_query->is_search()) {
        // Сохраняем текст поиска
        $search_term = $wp_query->get('s');

        // Формируем SQL-запрос для поиска страниц с шорткодами
        $search = "AND (
            {$wpdb->posts}.post_type = 'page' 
            AND {$wpdb->posts}.post_content LIKE '%[smoothslider%'
        )";

        // Стандартный SQL-подсчет постов
        $search .= " OR ({$wpdb->posts}.post_content LIKE '%$search_term%')";
    }

    return $search;
}

Объяснение:

  1. Фильтр posts_search: Этот фильтр позволяет изменять поисковый запрос на этапе формирования основных результатов поиска.

  2. Проверка условий: Код проверяет, что выполняется основной запрос и это поиск. В последующем используется глобальная переменная $wpdb для создания SQL-запроса.

  3. SQL-запрос: Он ищет страницы, которые содержат шорткод [smoothslider. Здесь можно адаптировать условия поиска, чтобы улучшить соответствие с запросом пользователя.

Перенаправление постов на родительские страницы

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

add_action('template_redirect', 'redirect_to_parent_page');
function redirect_to_parent_page() {
    if (is_singular('post')) {
        global $wpdb, $post;
        $slider_id = $wpdb->get_var("SELECT DISTINCT slide_id FROM {$wpdb->prefix}smooth_slider WHERE post_id = {$post->ID} LIMIT 1");
        $parent_page = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_status = 'publish' AND post_type = 'page' AND post_content LIKE '%[smoothslider id=\"$slider_id\"]%'");

        if ($parent_page) {
            wp_safe_redirect(get_permalink($parent_page));
            exit;
        }
    }
}

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...