API REST_ROUTE 404,同时为定制帖子构建过滤器(由多个元键/定制字段过滤)

时间:2022-02-10 作者:Ben Blue

我在WordPress网站工作,该网站有许多自定义帖子类型,并广泛使用高级自定义字段(ACF)。该网站还使用节点模块、从头开始的自定义代码和Git来支持预构建的主题和;“典型”;插件。我做的许多任务都涉及到使用已经编写的代码。

该网站是一家狩猎公司。我们有大陆、国家(有时在某些情况下称为目的地)、地方和推荐信——所有这些都是定制的帖子。其中没有一个使用任何分类法。通过ACF,推荐信已经有了自定义字段,将推荐信与相应的大陆、国家和地区连接起来。

我的问题很复杂,我会尽力解释的。

My goal创建一个Ajax过滤器,按大陆、国家和(最终)地点显示推荐信,无需插件。大陆和国家可以select 字段,并且只需要一个字段,也可以同时设置这两个字段。

该网站已经有一个几乎相同的版本,正在运行。它有下拉列表select筛选其他自定义邮件类型(行程)之一的。我需要的就是这样,只是为了纪念而不是行程。该页是https://extraordinaryjourneys.com/plan-your-trip/itineraries/.

它使用NPM Select-custom 还有一些PHP和JS文件。我在下面列出了其中的两个。

What I have tried我已经为推荐制作了重复的行程文件,并试图使这些工作就像行程页面的工作示例一样。写起来可能更容易meta_queries 如果是这样的话,我需要一些指导,但我认为这会更容易。这些是文件,包括我注释掉的部分,因为它们与行程页面上的下拉列表相关,而不需要在这个推荐页面上,比如行程预算,或者因为这是我了解这一切如何运作的一部分。

Where I am stuck我已经将代码推送到了临时站点,您可以看到控制台错误。你能帮我解决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的故障?

1 个回复
最合适的回答,由SO网友:Sally CJ 整理而成

正如我在评论中所说,我向您的自定义端点发出了POST请求(here) 然后收到一条404错误消息:“No No No modHFGen.dll未找到与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\';
<代码中的其他问题$metaQueries 变量未定义,应在if (isset($_REQUEST[\'continent\']) ...) 线

isset($_REQUEST[\'region\']) 应该not 被注释掉,否则如果region 参数,则您的自定义帖子查询将永远不会运行。

只有在以下情况下,上述帖子查询才会运行$metaQueries 有2个或更多项,因此如果数组为空或只有1个项,则$query 在您的return part将是一个未定义的部分,并导致PHP通知中显示Undefined variable: query.

这取决于你该如何解决。。但例如,您可以添加else, 并返回一个错误。

WP_Query 类使用非空的参数进行实例化,即。new WP_Query($args) 而不是new WP_Query(), 这个get_posts() 方法将自动调用,因此不应手动调用它。

因此,请更换$query->get_posts() 具有$query->posts 访问/检索通过自动调用get_posts() 方法

来自REST API handbook:

重要的是,REST API路由的回调应该始终返回数据;它不应该试图发送响应主体本身。这确保了REST API服务器所做的额外处理,如处理链接/嵌入、发送标头等。换句话说,不要打电话die( wp_json_encode( $data ) ); 或wp_send_json( $data ).

所以不要打电话wp_send_json_success() (使用wp_send_json()), 而且很简单return 数据。一、 e。return [ \'results\' => $result, ... ];

WordPress有一个__return_true() 函数,因此您可以\'permission_callback\' => \'__return_true\' :)

$args = array_merge($args, [ \'meta_query\' => $metaQueries ]); 可以写为$args[\'meta_query\'] = $metaQueries; ..