Sally_CJ
  • 0
Новичок

Api rest_route 404 при построении фильтра для пользовательских сообщений (отфильтрованных по нескольким метаключам/настраиваемым полям)

  • 0

Я работаю на сайте WordPress, который имеет множество настраиваемых типов сообщений и широко использует расширенные настраиваемые поля (ACF). Сайт также использует модули узлов, пользовательский код с нуля и Git в пользу предварительно созданной темы и «типичных» плагинов. Многие из моих задач связаны с работой с уже написанным кодом.

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

Моя проблема довольно сложная, и я сделаю все возможное, чтобы объяснить ее.

Моя цель Создать фильтр Ajax для отображения отзывов по континентам, странам и (в конечном итоге) местам без плагина. Континент и Страна могут быть selectполями, причем обязательно только одно, опционально можно задать оба.

На сайте уже есть почти идентичная версия этой, работающая. У него есть выпадающие списки select, которые фильтруют один из других настраиваемых типов сообщений, Маршруты. Мне нужно именно так, только для отзывов вместо маршрутов. Эта страница https://extraordinaryjourneys.com/plan-your-trip/itineraries/.

Он использует NPM Select-custom и несколько файлов PHP и JS. Я включил два из них ниже.

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

Там, где я застрял , я отправил код на промежуточный сайт, и вы можете увидеть ошибки консоли. Можете ли вы помочь мне устранить неполадки с вызовом API 404? Уже существующая страница маршрутов, указанная выше, имеет то же самое, но без ошибок. https://staging.extraordinaryjourneys.com/testimonial-troubleshooting. Вы можете выбрать континент или страну, и вы получите предупреждение, которое должно быть связано с вызовом API. Снимок экрана, показывающий, что вы увидите в консоли.

Если есть что еще включить или добавить, буду рад.

  • hero-filter-testimonials.js
import '../elements/filter-results-grid';

$(document).ready(function () {
   const $body = $('body');
   const $filterTestimonials = $('.filter-testimonials');
   
   $body.on('click', '.btn-load-more', function (e) {
       $(e.currentTarget).hide();
       getResults(null, parseInt(e.currentTarget.dataset.page));
   });

   $('.clear-all').click(function () {
       window.history.replaceState(null, null, '#');
       triggerSearch(getParamsObject(), $filterTestimonials);
   });

   continentContainer.find('.custom-select__option').on('click', function (e) {
       let continentId = e.currentTarget.dataset.value;
       showCountriesOptions(continentId);
   });

   function showCountriesOptions(continentId = null) {
       const $selectContainer = $filterTestimonials.find('#destination').parent();
       console.log('Line 38 hero-filter-testimonials.js: continentId: ' + continentId);
       if (continentId) {
           $selectContainer.find('.custom-select__option').hide();
           $selectContainer.find(".custom-select__option[data-continent='" + continentId + "']").show();
       } else {
           $selectContainer.find('.custom-select__option').not('[data-value="placeholder"]').show();
       }
   }

   function getResults(origin = null, page = 1) {
       console.log("getResults(): " + getResults);
       let data = {action: 'get_testimonial_results'};

       $filterTestimonials.find('.filter-panel').hide();

       const $select = $filterTestimonials.find('.custom-select');

       data = getDataFromSelectors(data, $select);

       if (origin && origin === 'continent') {
           if (data['destination']) {
               delete data['destination'];
               resetSingleSelector($filterTestimonials.find('#destination')[0]);
           }
       }

      $filterTestimonials.find('#special_departures').prop("checked");
       console.log("Line below is log.data");
       console.log(data);
       console.log("Line below is dir.data");
       console.dir(data);
       updateUrl(data);

       if (Object.keys(data).length === 1) {
           getContainer().show();
           getResultsContainer().hide();
           $body.find('.clear-all-btn-container').hide();
       } else {
           let $loader = $body.find('.filter-loader');
           $body.find('.clear-all-btn-container').show();
           getFilterResults('get_testimonial_results', 'Testimonials', data, $loader, page);
       }
       addBadges($filterTestimonials, ['continent']);
   }

   window.getResults = getResults;

   let data = getParamsObject();
   console.log("Line below is data");
   console.table(data);
   console.log("Line below is $filterTestimonials");
   console.table($filterTestimonials);
   // console.log(JSON.stringify($filterTestimonials,null,2));
   triggerSearch(data, $filterTestimonials);
});
  • testimonials_results.phpЭта страница делает пользовательский вызов API, который возвращает 404, и я не знаю, почему. У него также есть запрос для получения сообщений с отзывами.
<?php

add_action('rest_api_init', function () {
    register_rest_route('ejourneysnineteen/v1', '/get_testimonial_results', array(
        'methods' => 'POST',
        'callback' => 'get_testimonial_results',
        'permission_callback' => function () {
            return true;
        }
    ));
});

function get_testimonial_results() {
    $pageSize = $_REQUEST['pageSize'] ?? 10;

    $args = [
        'posts_per_page' => $pageSize,
        'ignore_sticky_posts' => 1,
        'post_type' => 'testimonial',
        'orderby' => 'title',
        'order' => 'ASC',
    ];

    if (isset($_REQUEST['page'])) {
        $args['paged'] = $_REQUEST['page'];
    }

    if (isset($_REQUEST['continent']) || 
     isset($_REQUEST['destination']) 
    //  isset($_REQUEST['region']) ||
    //  isset($_REQUEST['accommodation_type']
     ) {
        // $metaQueries = ['relation' => 'AND'];

        if (isset($_REQUEST['region'])) {
            $regions = explode(',', $_REQUEST['region']);
            $subquery = [
                'relation' => 'OR'
            ];
            foreach ($regions as $region) {
                $subquery[] = [
                    'key' => 'accommodation_region',
                    'value' => $region,
                    'compare' => 'LIKE'
                ];
            }
            $metaQueries[] = $subquery;
        }
        else {
            if (isset($_REQUEST['destination'])) {
                $metaQueries[] = [
                    'key' => 'testimonial_country',
                    'value' => $_REQUEST['destination'],
                    'compare' => 'LIKE',
                ];
            }
            else {
                if (isset($_REQUEST['continent'])) {
                    $metaQueries[] = [
                        'key' => 'testimonial_continent',
                        'value' => $_REQUEST['continent'],
                        'compare' => 'LIKE',
                    ];
                }
            }
        }

              $args = array_merge($args, [
            'meta_query' => $metaQueries
        ]);
    }

    $result = [];
    if (count($metaQueries) > 1) {
        $query = new WP_Query($args);

        foreach ($query->get_posts() as $post) {
            $post_thumbnail_id = get_post_thumbnail_id($post);
            $image_url = fly_get_attachment_image_src($post_thumbnail_id, [500, 500], true);
            $result[] = [
                'link' => get_the_permalink($post),
                'title' => $post->post_title,
                'excerpt' => html_entity_decode(ellipsis(get_the_excerpt($post), 80)),
                'image_url' => $image_url,
                'category' => 'Testimonial'
            ];
        }
    }
    wp_send_json_success([
        'results' => $result,
        'total' => $query->found_posts,
        'pages' => $query->max_num_pages,
        ]);
}

Есть и другие файлы, но я так застрял, что не уверен, должен ли я добавить их все туда или нет. Этого достаточно, чтобы помочь мне устранить неполадки с вызовом API 404?

Share
  1. (Да, я уже пробовал с POST-запросом, и это не сработало, но просто убедился, что ваш AJAX использует метод POST-запроса ). Кроме того, «Снимок экрана здесь» — где он? И на самом деле, вместо создания пользовательской конечной точки, вы можете просто использовать rest_testimonial_query хук для изменения аргументов запроса, чтобы вы могли просто использовать конечную точку по умолчанию для получения сообщений с отзывами.

    • 0
  2. В вашем коде есть и другие проблемы (например, $metaQueries должен быть определен перед if (isset($_REQUEST['continent'])...) строкой), но что касается ошибки 404, полное сообщение, которое я видел ( здесь через запрос POST ): « Не найден маршрут, соответствующий URL-адресу и методу запроса.. «, так как вы загружаете testimonials_results.php файл? Это include -d или require -d из functions.php файла? Ваш запрос AJAX действительно делает запрос POST ?

    • 0
  3. Привет, Салли, оказывается, я вообще не загружался testimonials_results . Я добавил его как require_once in functions.php . Вот и избавился от 404! Спасибо, что заглянули. Что для этого лучше всего здесь — отредактировать вопрос для других вопросов, проголосовать за комментарий или что-то еще?

    • 0
  4. Честно говоря, я тоже не слишком уверен. Но вы можете просто опубликовать ответ на основную проблему (ошибка 404). В любом случае, я опубликовал ответ, а также ответил на другие вопросы.

    • 0
  5. В любом случае, спасибо за крутые комментарии! Я только сейчас возвращаюсь к этому и ссылаюсь на ваши советы.

    • 0
  6. Как я сказал в своем комментарии, я сделал POST-запрос к вашей пользовательской конечной точке ( здесь ), а затем получил ошибку 404 с этим сообщением: « Не найдено маршрута, соответствующего URL-адресу и методу запроса », что, вероятно , означает, что маршрут никогда не был зарегистрирован, либо метод запроса не поддерживается, т.е. отсутствует в methodsсписке, указанном при регистрации (используя register_rest_route()).

    Таким образом, вам просто нужно убедиться, что маршрут зарегистрирован правильно и что ваш (AJAX) запрос использует правильный метод HTTP-запроса, и тогда ошибка 404 исчезнет.

    И в вашем случае вы можете убедиться, что маршрут зарегистрирован правильно, загрузив testimonials_results.phpфайл из файла темы functions.php. Например

    // Assuming the file is at the same level as the functions.php file
    require_once __DIR__ . '/testimonials_results.php';
    

    Другие проблемы в вашем коде

    1. Переменная $metaQueriesне определена и должна быть определена перед if (isset($_REQUEST['continent'])...)строкой.

    2. Не isset($_REQUEST['region'])следует закомментировать, потому что в противном случае, если бы был указан только параметрregion , ваш пользовательский запрос сообщений никогда не выполнялся бы.

    3. Приведенный выше запрос сообщений также будет выполняться только в том случае, если $metaQueriesон содержит 2 или более элементов, поэтому, если массив пуст или содержит только 1 элемент, $queryв вашей returnчасти будет неопределенное значение, и в результате появится уведомление PHP, говорящее Undefined variable: query.

      И вам решать, как это исправить… но, например, вы можете добавить elseи вернуть ошибку.

    4. Когда WP_Queryкласс создается с непустыми аргументами, т.е. new WP_Query($args)в отличие от new WP_Query(), get_posts()метод будет вызываться автоматически, поэтому вам не следует вызывать его вручную.

      Поэтому замените на $query->get_posts()для $query->postsдоступа/получения сообщений, которые уже были получены с помощью автоматического вызова get_posts()метода.

    5. Из справочника REST API :

      Важно отметить, что обратный вызов маршрута REST API всегда должен возвращать данные; он не должен пытаться отправить само тело ответа. Это гарантирует, что дополнительная обработка, которую выполняет сервер REST API, такая как обработка связывания/встраивания, отправка заголовков и т. д., имеет место. Другими словами, не звоните die( wp_json_encode( $data )); или wp_send_json( $data ).

      Так что не звоните wp_send_json_success()(который использует wp_send_json()), а просто возвращайте данные. то естьreturn [ 'results' => $result,... ];

    Дополнительные примечания/информация

    1. В WordPress есть __return_true()функция, так что вы можете просто сделать 'permission_callback' => '__return_true'🙂

    2. Можно $args = array_merge($args, [ 'meta_query' => $metaQueries ]);было бы просто написать как $args['meta_query'] = $metaQueries;..

    • 0

Оставить ответ

You must login to add an answer.