最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Custom REST endpoint not working to retrieve single posts ("rest_no_route")

programmeradmin0浏览0评论

I've got the following basic route for my custom REST endpoint:

add_action('rest_api_init', 'my_cpt_route');
function my_cpt_route() {
    register_rest_route('mytheme/v1/', 'my_cpt', array(
        'methods' => WP_REST_SERVER::READABLE,
        'callback' => 'my_cpt_results',
    ));
}

And this is the CB function:

function my_cpt_results() {
    $args = array(
        'post_type' => array('my_cpt'),
        'posts_per_page' => -1,
    );
    $mainQuery = new WP_Query($args);

    $results = array();

    while ($mainQuery->have_posts()) {
        $mainQuery->the_post();
        
        array_push($results, array(
            'id' => get_the_ID(),
            'title' => get_the_title(),
            'url' => get_the_permalink(),
            'image' => array(
                'small' => get_the_post_thumbnail_url(0, 'thumbnail'),
                'medium' => get_the_post_thumbnail_url(0, 'medium'),
                'large' => get_the_post_thumbnail_url(0, 'large'),
            )
        ));
        $results = array_values(array_unique($results, SORT_REGULAR));
    }
   
    wp_reset_postdata();
    
    return $results;
}

This works just fine when I retrieve all the posts (so if I go to "/wp-json/mytheme/v1/my_cpt/" I get all the CPT posts).

What I expected is that if I append an id of a published CPT post at the end of the URL (eg.: "/wp-json/mytheme/v1/my_cpt/56") I had to get only the post with id 56. Instead, I get a 404 "rest_no_route". Maybe I need to modify the register_rest_route args? (but how?)...

UPDATE

...and how to get the same results using this functions as class methods? I'm not much into OOP and I'd like to learn... Say I've got the following simple class (based on wppb.me plugin boilerplate):

class My_Routes {
/**
 * The ID of this plugin.
 *
 * @since    1.0.0
 * @access   private
 * @var      string    $plugin_name    The ID of this plugin.
 */
private $plugin_name;

/**
 * The version of this plugin.
 *
 * @since    1.0.0
 * @access   private
 * @var      string    $version    The current version of this plugin.
 */
private $version;

/**
 * Initialize the class and set its properties.
 *
 * @since    1.0.0
 * @param      string    $plugin_name       The name of this plugin.
 * @param      string    $version    The version of this plugin.
 */
public function __construct($plugin_name, $version)
{

    $this->plugin_name = $plugin_name;
    $this->version = $version;
}

/**
 * Creates routes
 */
public static function register_cpt_routes()
{
    register_rest_route('mytheme/v1/', 'my_cpt', array(
            'methods' => WP_REST_SERVER::READABLE,
            'callback' => array( $this, 'get_posts' ),
        ));
    register_rest_route('mytheme/v1/', 'my_cpt/(?P<id>[\d]+)', array(
            'methods' => WP_REST_SERVER::READABLE,
            'callback' => array( $this, 'get_post' ),
        ));
}

/**
 * Callback function to load all posts
 */
public static function get_posts()
{
    // ...do stuff for getting all the posts, and this is working
}

/**
 * Callback function to load a single post
 */
public static function get_post($data)
{
    // How do I pass the $data args to the get_post method?
    
    $cpt_id = $data['id'];
    // ...do stuff
}

}

I've got the following basic route for my custom REST endpoint:

add_action('rest_api_init', 'my_cpt_route');
function my_cpt_route() {
    register_rest_route('mytheme/v1/', 'my_cpt', array(
        'methods' => WP_REST_SERVER::READABLE,
        'callback' => 'my_cpt_results',
    ));
}

And this is the CB function:

function my_cpt_results() {
    $args = array(
        'post_type' => array('my_cpt'),
        'posts_per_page' => -1,
    );
    $mainQuery = new WP_Query($args);

    $results = array();

    while ($mainQuery->have_posts()) {
        $mainQuery->the_post();
        
        array_push($results, array(
            'id' => get_the_ID(),
            'title' => get_the_title(),
            'url' => get_the_permalink(),
            'image' => array(
                'small' => get_the_post_thumbnail_url(0, 'thumbnail'),
                'medium' => get_the_post_thumbnail_url(0, 'medium'),
                'large' => get_the_post_thumbnail_url(0, 'large'),
            )
        ));
        $results = array_values(array_unique($results, SORT_REGULAR));
    }
   
    wp_reset_postdata();
    
    return $results;
}

This works just fine when I retrieve all the posts (so if I go to "http://mysite.test/wp-json/mytheme/v1/my_cpt/" I get all the CPT posts).

What I expected is that if I append an id of a published CPT post at the end of the URL (eg.: "http://mysite.test/wp-json/mytheme/v1/my_cpt/56") I had to get only the post with id 56. Instead, I get a 404 "rest_no_route". Maybe I need to modify the register_rest_route args? (but how?)...

UPDATE

...and how to get the same results using this functions as class methods? I'm not much into OOP and I'd like to learn... Say I've got the following simple class (based on wppb.me plugin boilerplate):

class My_Routes {
/**
 * The ID of this plugin.
 *
 * @since    1.0.0
 * @access   private
 * @var      string    $plugin_name    The ID of this plugin.
 */
private $plugin_name;

/**
 * The version of this plugin.
 *
 * @since    1.0.0
 * @access   private
 * @var      string    $version    The current version of this plugin.
 */
private $version;

/**
 * Initialize the class and set its properties.
 *
 * @since    1.0.0
 * @param      string    $plugin_name       The name of this plugin.
 * @param      string    $version    The version of this plugin.
 */
public function __construct($plugin_name, $version)
{

    $this->plugin_name = $plugin_name;
    $this->version = $version;
}

/**
 * Creates routes
 */
public static function register_cpt_routes()
{
    register_rest_route('mytheme/v1/', 'my_cpt', array(
            'methods' => WP_REST_SERVER::READABLE,
            'callback' => array( $this, 'get_posts' ),
        ));
    register_rest_route('mytheme/v1/', 'my_cpt/(?P<id>[\d]+)', array(
            'methods' => WP_REST_SERVER::READABLE,
            'callback' => array( $this, 'get_post' ),
        ));
}

/**
 * Callback function to load all posts
 */
public static function get_posts()
{
    // ...do stuff for getting all the posts, and this is working
}

/**
 * Callback function to load a single post
 */
public static function get_post($data)
{
    // How do I pass the $data args to the get_post method?
    
    $cpt_id = $data['id'];
    // ...do stuff
}

}

Share Improve this question edited Jun 29, 2020 at 16:05 Paolo Sacchetti asked May 3, 2020 at 17:28 Paolo SacchettiPaolo Sacchetti 238 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

To get your expected result, you have to create a second endpoint. Your endpoint doesn't know what to do with the last part of the path (the ID).

register_rest_route('mytheme/v1/', 'my_cpt/(?P<id>[\d]+)', array(
    'methods' => WP_REST_SERVER::READABLE,
    'callback' => 'my_cpt_single_result',
));

Your CB function could be like this:

function my_cpt_single_result( $data ) {
   $cpt_id = $data['id'];
   // make your query with the $cpt_id
}

A little more validation should be done. It is explained here in a longer version.

发布评论

评论列表(0)

  1. 暂无评论