Getting pages by url using WordPress REST API

I’m attempting to using WP REST API on a site that uses pretty URLs, not ID’s (which is typical in a REST scenario). All I have to query with is the requested URL.

Lets say a user lands on example.com/about, I can do the following:

Read More
/wp-json/wp/v2/pages/?slug=about

No sweat. However, what if a users lands on example.com/about/team? I could query by the slug team, but maybe my site also has example.com/contact/team as a possible URL. It’s not reliable.

What I need is a way of achieving the following:

/wp-json/wp/v2/pages/?permalink=about%2team

It’s unfeasible to have to set up custom routes for each page that gets created. I’m surprised the API doesn’t appear to have some kind of permalink handler out of the box.

Related posts

1 comment

  1. Well, since there is no tool to handle all of the cases, you have to be a bit crafty. It is possible to use a combination of wp functions like url_to_postid or get_term_by and global variables like $wp_taxonomies to figure out all of the cases.

    You can create a custom endpoint and use the code below to handle the path. I think that I have covered all of the possible cases, but use carefully cause I might miss something.

    function ca_path_to_object($path = '/') {
        $path = $path === '/' ? $path : trim($path, '/');
        $path = $path === '' ? '/' : $path; // Return homepage for no arguments
        $for_front = intval(get_option('page_on_front'));
        $for_posts = intval(get_option( 'page_for_posts' ));
        if($path == '/') $pid = $for_front; // It is the homepage
        else $pid = url_to_postid($path); // It is not
        if($for_posts != 0) { //For some reason url_to_postid does not work if the page is set to be the blog feed
            if($for_posts == $for_front) { // if both $for_front & $for_posts set to the same page get_permalink returns 404 for some reason, so lets construct it manually
                $pst = get_post($for_posts);
                $prnt = intval($pst->post_parent);
                $url = '';
                if($prnt != 0) {
                    $url = parse_url(get_permalink($prnt));
                    $url = trim($url['path'], '/');
                }
                $url .= '/'.$pst->post_name;
                // if it matches it will return the results as Homepage as per default WP behaviour
            }
            else {
                $url = parse_url(get_permalink($for_posts)); // otherwise just get it
                $url = $url['path'];
            }
            if(trim($url, '/') == $path) $pid = $for_posts;
        }
        if($pid == 0) { // not a page or cpt, let's try to find a taxonomy out of it
            $path_arr = explode('/', $path);
            global $wp_taxonomies;
            $tax = null;
            foreach ($wp_taxonomies as $key => $value) {
                if ($value->rewrite['slug'] === $path_arr[0]){
                    $tax = $key;
                }
            }
            if($tax !== null) {
                $term = get_term_by('slug', end($path_arr), $tax);
                if($term !== false) {
                    $pid = $term->term_id;
                    return array(
                        'type' => 'term',
                        'id' => $term->term_id,
                        'object' => $term,
                    );
                }
            }
        }
        if($pid == 0) { // If still 0, perhaps it's an user profile url?
            global $wp_rewrite;
            $base = explode('/', trim($wp_rewrite->get_author_permastruct(), '/'));
            $base = $base[0];
            if($path_arr[0] === $base) {
                $user = get_user_by('slug', end($path_arr));
                if($user !== false) {
                    $pid = $user->ID;
                    return array(
                        'type' => 'user',
                        'id' => $user->ID,
                        'object' => $user,
                    );
                }
            }
        }
        if(($pid == 0) && ($path == '/')) { // If still 0, lets check if the page is the homepage without any associated page entity
            return array(
                'type' => 'home',
                'id' => null,
                'object' => null,
            );
        }
        if($pid == 0) { // If still 0, return nothing found or 404
            return array(
                'type' => '404',
                'id' => null,
                'object' => null,
            );
        }
        $post = get_post($pid);
        if($post->ID == $for_front) { // It's a page assigned to be a homepage
            return array(
                'type' => 'home',
                'id' => $post->ID,
                'object' => $post,
            );
        }
        if($post->ID == $for_posts) { // It's a page assigned to be a posts feed
            return array(
                'type' => 'feed',
                'id' => $post->ID,
                'object' => $post,
            );
        }
        return array( // It's just a post object
            'type' => 'post',
            'id' => $post->ID,
            'object' => $post,
        );
    }
    

Comments are closed.