WP JSON list all permalinks

The question:

Scenario

I’m considering writing a custom wp-json endpoint to list ALL permalinks for everyone post in my wordpress.

Question

Is it possible to do this with a rest query + filters? eg. http://wpsite.com/wp-json/wp/v2/posts?filter[only-permalinks]

Current Solution

I ended up writing a custom endpoint, code below:

added to the bottom of functions.php

function get_all_slugs() {
    $posts = get_posts( array(
        'numberposts' => -1,
        'post_type' => "screen",
    ) );

    if ( empty( $posts ) ) {
        return null;
    }

    $posts_data = array();

    foreach( $posts as $post ) {
        $id = $post->ID; 
        
        $posts_data[] = (object) array( 
            'id' => $id, 
            'slug' => $post->post_name, 
            //'title' => $post->post_title,
        );
    }

    return $posts_data;
}
add_action( 'rest_api_init', function () {
    register_rest_route( 'row/v1', '/all-slugs', array( // /(?P<post_type>d+)', array(
        'methods' => 'GET',
        'callback' => 'get_all_slugs',
    ) );
} );

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

Is it possible to do this with a rest query + filters? eg.
http://wpsite.com/wp-json/wp/v2/posts?filter[only-permalinks]

Yes, since 4.9.8 (see #43874) it’s possible to render only fields needed with the _fields parameter.

Examples

Render only the permalinks:

https://example.com/wp-json/wp/v2/posts?_fields=link

[ 
    {
        link: "https://example.com/foo/"
    },
    {
        link: "https://example.com/bar/"
    },
]

Render only the post IDs and permalinks:

https://example.com/wp-json/wp/v2/posts?_fields=id,link

[ 
    {
        id: 123,
        link: "https://example.com/foo/"
    },
    {
        id: 234,
        link: "https://example.com/bar/"
    },
]

Render only the post IDs and the slugs:

https://example.com/wp-json/wp/v2/posts?_fields=id,slug

[ 
    {
        id: 123,
        slug: "foo"
    },
    {
        id: 234,
        slug: "bar"
    },
]

Fetching All Available Items

Currently we have to fetch all available items with paging, like:

https://example.comwp-json/wp/v2/posts?_fields=slug&per_page=100&page=1
https://example.comwp-json/wp/v2/posts?_fields=slug&per_page=100&page=2
...

where per_page is 10 by default and with maximum value of 100.

Fetching all items in a single request can result in fatal errors if the number of items exceeds the available resources.

The ticket #43998 to allow unbound requests (something like per_page=-1) for logged in users, was closed as wontfix because it doesn’t scale and has performance issues.

There’s a ticket #45140 to increase the upper bound for per_page to few hundreds.

Usually there’s no need to display so many items in a user interface and there exists javascript techniques to handle the pagination.

If more is really needed then one could filter the rest query via rest_{$post_type}_query to override the maximum default value of posts_per_page, at the risk of fatal errors if available resources are exceeded.

Method 2

I don’t believe there is a default endpoint to let you get all the posts and return only the permalinks.

You could use the posts endpoint to get large chunks of permalinks (I don’t believe it will let you return all of them in a single request) and paginate the request. To get it to return only the permalinks you could use the json_prepare_post filter all of which is outlined as part of this tutorial.

However, if you must have all the permalinks in a single return, the most efficient way of doing it would be to add a new endpoint as outlined here. In the callback function you could do something like this but instead of echoing the permalinks put them in an array, json_encode() the array, and then return it.

Since this could become a monster of a process with a lot of posts, I’d recommend using the Transient API to store the request(s) – whether you choose to paginate and use the posts endpoint or return everything with a custom endpoint.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment