Using "orderby" params with meta field always results in 400 Bad Request

Hello all,

I am trying to build (what I think is) a simple website to show stars from the HYG database. As a Wordpress developer diving deeper into ReactJS, I thought this would be a great way to learn how to integrate the two. I’ve been running into some issues, however, and I am now stumped.

At the moment, I would like the default behavior to have the stars sorted by distance from Earth, ascending. So I put the following in my frontity.settings.js:

"state": {
        "source": {
          "url": "http://localhost:10004",
          "postTypes": [
            {
              type: "astrog_star", // Prefixing with plugin namespace "astrog_" to avoid conflicts
              endpoint: "stars", // '/wp/v2/stars'
              archive: "/", // I want these to appear on the homepage
            }
          ],
          "params": {
            per_page: 100,
            orderby: "distance", // This will later be changed to "astrog_distance" for clarity
            order: "asc",
            type: ["astrog_star"],
          },
        }
      }

The “distance” field is a meta field I’ve added. Looking at the WP api endpoints, I see that it isn’t one of the args under my custom post type endpoint, so I’ve been looking for examples of code that does exactly that. I’ve examined this gist, this blog post by Tim Ross, this post from Shishir Raven, and this StackOverflow post. So far, none of these solutions have worked, and in some places even appear contradictory to me (for example, that gist puts down “meta_value_num” into the $params['orderby']['enum'] value through the collection params filter hook, but Tim Ross and others put down the meta_key instead.) I really don’t know what to think or do here.

I have the following in my plugin file, astrographer.php, though right now it’s just a combination of different ideas and I’m commenting certain functions out and in to try and test what combination might work. You can see my repo here.

// Adding custom fields to rest

add_action( 'rest_api_init', 'astrog_star_register_fields');
function astrog_star_register_fields(){
   foreach (['spect', 'distance', 'astrog_lumos', 'astrog_hue'] as $field) {
       register_rest_field('astrog_star',
       $field,
       [
           'get_callback' => 'astrog_star_get_field',
           'update_callback' => null,
           'schema' => null,
       ]);
   }
}

add_action('rest_api_init', 'astrog_star_orderby');
function astrog_star_orderby(){

     add_filter("rest_endpoints", function($routes){
        $route = $routes['/wp/v2/stars'];
        $route['endpoints'][0]['args']['orderby']['enum'][] = 'meta_value';
        $route['endpoints'][0]['args']['meta_key'] = [
            'description' => 'The meta key to query',
            'type' => 'float',
            'enum' => ['distance'],
            'validate_callback' => 'rest_validate_request_arg',
        ];
        return $routes;
    }, 10,1);

    add_filter("rest_stars_collection_params", function( $params ){
        $params['orderby']['enum'][] = "distance";
        return $params;
    },10,1);

    add_filter("rest_stars_query", function($args, $request){
        $orderkey = $request->get_param('orderby');
        if( isset($orderkey) && 'distance' === $orderkey ) {
            $args['meta_key'] = $orderkey;
            $args['orderby']['enum'] = 'meta_value';
        }
        return $args;
    },10,2);
}

/*
 * Get the value of the meta fields
 * @param array $object Details of current post.
 * @param string $field_name Name of field.
 * @param WP_REST_Request $request Current request
 *
 * @return mixed
*/

function astrog_star_get_field($object, $field_name, $request){
    return get_post_meta($object['id'], $field_name, true);
}

function astrog_add_meta_vars ($current_vars) {
    $current_vars = array_merge($current_vars, array('meta_key', 'meta_value', 'meta_value_num'));
    return $current_vars;
}

add_filter('query_vars', 'astrog_add_meta_vars');

No matter what I do, however, I always get a 400 - Bad Request response, and I believe it’s because my code isn’t adding the fields to the ['endpoints'][0]['args']['orderby']['enum'] array, as shown in the picture below. I thought the hook to us in order to add these would be rest_api_init, but maybe I’m wrong? I’m not sure where to look for answers at this point.

A few points:

  1. I’m using filters like “rest_stars_collection_params” and not “rest_astrog_stars_collection_params” because according to the Wordpress API docs “The dynamic part of the filter $this->post_type refers to the post type slug for the controller.” And, in custom_star_type.php, I have both 'rewrite' => ['slug' => 'stars'] and 'rest_base' => 'stars' as I thought having astrog_star in every url would be too much. Am I misreading the docs?

  2. I’m currently developing this on local with Flywheel’s Local tool. That wouldn’t be causing an issue, would it?

  3. Related, but after I solve this issue I want to add filtering tools for users. I was initially looking at purely React filter code, which you can see in Grid.js, but that always returns blanks (and even blanks out what is already there, if I’m not running into this bad request issue.) Would I use Frontity actions and/or libraries to modify the request to achieve this? I figure if I/we can solve my current problem, this filtering one should go a lot more smoothly.

To round this out, here’s my npx frontity info data:

## System:
 - OS: Windows 10 10.0.19042
 - CPU: (8) x64 Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz
 - Memory: 19.38 GB / 31.95 GB
## Binaries:
 - Node: 16.13.1 - C:\Program Files\nodejs\node.EXE
 - npm: 8.1.2 - C:\Program Files\nodejs\npm.CMD
## Browsers:
 - Chrome: Not Found
 - Edge: Spartan (44.19041.1266.0), Chromium (99.0.1150.46)
 - Internet Explorer: 11.0.19041.1566
## npmPackages:
 - @frontity/core: ^1.14.3 => 1.14.3
 - @frontity/html2react: ^1.7.0 => 1.7.0
 - @frontity/mars-theme: ./packages/mars-theme => 1.6.2
 - @frontity/tiny-router: ^1.4.4 => 1.4.4
 - @frontity/wp-source: ^1.11.7 => 1.11.7
 - frontity: ^1.17.1 => 1.17.1
## npmGlobalPackages:
 - frontity: Not Found
 - npx: Not Found