WordPress Rest API get All Posts
Asked Answered
B

5

7

I am using the following to get posts

http://demo.wp-api.org/wp-json/wp/v2/posts

This by default gives me 10 posts, which is mentioned in the docs.

But I want all the posts without having to keep track of pagination.

Is that possible?

If not is there a way I can run a JavaScript loop to get all posts?

Thanks.

Budweis answered 29/1, 2018 at 5:7 Comment(4)
You can pass arguments to the request URL. So the following would return 50 posts; www.mywebsite.com/wp-json/wp/v2/posts?per_page=50 Unfortunately the per_page argument must be between 1 (inclusive) and 100 (inclusive). If you have over 100 posts and needed all posts regardless, you'd have to send multiple requests and specify the offset argument correctly to retrieve all posts.Bentwood
check these post #35729443, michaelsoriano.com/get-all-posts-from-wordpress-rest-apiBentwood
@Bentwood Yes, I read the posts you have linked to. It looks like the top limit for posts is 100. Is there a way I can get the total NUMBER of posts? So I would know how many requests to make.Budweis
Possible duplicate of Wordpress REST API V2 return all postsErythroblastosis
E
0

One way to solve this is with RxJS

We'll build a small Observable stream that will:

  • Output all post data
  • Not force us to know total number of posts OR pages beforehand
  • Not force to keep track of "where we're at" in the context of pagination

Libraries we'll use:

  • Axios (To simplify the HTTP GET, as it works both in Node and Browser environments)
  • RxJS v6 (Currently an Alpha release, but the API here is the same for RxJS 5)

Your environment and use case will vary, for this example I'm going to be in a Node environment.

/**
 *      This will get all posts from a default WordPress REST API
 *      First we see how many pages there are
 *      Then we make subsequent XHR requests (via Axios)
 *      That paginate through every page of posts
 */

// Importing Axios for simple AJAX request
const axios = require('axios')

// Importing RxJS @ v6.0.0-alpha.3
const { Observable, from, range } = require('rxjs')
const { switchMap, concatMap } = require('rxjs/operators')

const endpoint = 'http://demo.wp-api.org/wp-json/wp/v2/posts'

/**
 *      This sets up the initial request and the Observable stream
 *      In the return from the endpoint, the Axios request headers will have x-wp-totalpages,
 *      which gives us... the total pages of posts ;)
 */
const posts$ = Rx.Observable.from(axios.get(endpoint))
    /**
     *     We now know the total number of pages,
     *     so we'll switch to a new Observable that is just a range of numbers
     *     We'll start with 1, and end with whatever the total number of pages is
     *     This gives us a stream of 1--n--n--n... (example: 1, 2, 3, 4...)
     */
    .switchMap((
        { headers }, // using ES6 function header destructuring and arrow functions here
    ) => Rx.Observable.range(1, Number(headers['x-wp-totalpages'])))
    /**
     *     We can now paginate through all posts, getting 10/page
     *     concatMap will fire off a request, waits until it completes, and then fire the next one
     *     In each subsequent firing, we ask for the next page of posts
     */
    .concatMap(page =>
        axios.get(endpoint, {
            params: {
                page,
            },
        }),
    )
    .subscribe(
        // data here is an Array of WordPress Posts, tacking .length shows us how many per page we are getting
        ({ data }) => console.log(data.length),
        err => console.log('Oh no, an error!', err),
    )

Resources

Erythroblastosis answered 3/2, 2018 at 21:8 Comment(0)
O
0

You may can use wp_remote_retrieve_body($url) OR wp_remote_post($url) to grab post data instead of rest API usage. wp_remote functions are independent of default pagination.

Orelie answered 29/1, 2018 at 6:2 Comment(0)
E
0

One way to solve this is with RxJS

We'll build a small Observable stream that will:

  • Output all post data
  • Not force us to know total number of posts OR pages beforehand
  • Not force to keep track of "where we're at" in the context of pagination

Libraries we'll use:

  • Axios (To simplify the HTTP GET, as it works both in Node and Browser environments)
  • RxJS v6 (Currently an Alpha release, but the API here is the same for RxJS 5)

Your environment and use case will vary, for this example I'm going to be in a Node environment.

/**
 *      This will get all posts from a default WordPress REST API
 *      First we see how many pages there are
 *      Then we make subsequent XHR requests (via Axios)
 *      That paginate through every page of posts
 */

// Importing Axios for simple AJAX request
const axios = require('axios')

// Importing RxJS @ v6.0.0-alpha.3
const { Observable, from, range } = require('rxjs')
const { switchMap, concatMap } = require('rxjs/operators')

const endpoint = 'http://demo.wp-api.org/wp-json/wp/v2/posts'

/**
 *      This sets up the initial request and the Observable stream
 *      In the return from the endpoint, the Axios request headers will have x-wp-totalpages,
 *      which gives us... the total pages of posts ;)
 */
const posts$ = Rx.Observable.from(axios.get(endpoint))
    /**
     *     We now know the total number of pages,
     *     so we'll switch to a new Observable that is just a range of numbers
     *     We'll start with 1, and end with whatever the total number of pages is
     *     This gives us a stream of 1--n--n--n... (example: 1, 2, 3, 4...)
     */
    .switchMap((
        { headers }, // using ES6 function header destructuring and arrow functions here
    ) => Rx.Observable.range(1, Number(headers['x-wp-totalpages'])))
    /**
     *     We can now paginate through all posts, getting 10/page
     *     concatMap will fire off a request, waits until it completes, and then fire the next one
     *     In each subsequent firing, we ask for the next page of posts
     */
    .concatMap(page =>
        axios.get(endpoint, {
            params: {
                page,
            },
        }),
    )
    .subscribe(
        // data here is an Array of WordPress Posts, tacking .length shows us how many per page we are getting
        ({ data }) => console.log(data.length),
        err => console.log('Oh no, an error!', err),
    )

Resources

Erythroblastosis answered 3/2, 2018 at 21:8 Comment(0)
G
0

Large queries can hurt site performance, so per_page is capped at 100 records. If you wish to retrieve more than 100 records, for example to build a client-side list of all available categories, you may make multiple API requests and combine the results within your application. See this page for a complex explanation

Gessner answered 5/2, 2018 at 19:39 Comment(0)
J
0

You can use this function in node.js

const getAllPosts = async (wordpressUrl) => {
  const url = `${wordpressUrl}/wp-json/wp/v2/posts?per_page=100`

  const maxPages = 50
  let page = 1
  let text
  const responses = []
  while (true) {
    const urlWithPage = `${url}&page=${page}`
    const res = await fetch(urlWithPage)
    text = await res.text()
    text = text.trim()
    if (res.status !== 200) {
      break
    }
    if (text === '[]') {
      break
    }
    if (!text.match(/^\[/) || !text.match(/\]$/)) {
      break
    }
    text = text.replace(/^\[/, '').replace(/\]$/, '')
    responses.push(text)

    if (page > maxPages) {
      break
    }
    page++
  }

  // get all pages and join them
  if (responses.length) {
    return `[${responses.join(',')}]`
  }

  // if didn't get any valid repsonses, send the text received
  return text
}
Jus answered 15/5, 2020 at 5:1 Comment(0)
V
0

I am writing an app in react native using typescript, but the underlying principals of paginating through the results of a wordpress GET request are going to be similar.

  1. I make a request using a 'page' query parameter initialized as 1 (fight the tempation to start at 0 here).
  2. I get the "x-wp-totalpages" (returned via the the response headers) which is the total number of "pages" or batches of posts to be received
  3. I compare the total number of pages against my current variable and recursively call the function until my array is all filled up with the posts.

It helped me to read the Wordpress REST API pagination documentation

async getPosts(current = 1, allPosts = []): Promise < Types.GetPostsResult > {
  // make the api call
  const response: ApiResponse < ApiFeedResponse > = await this.apisauce.get(
    Config.API_URL + '/posts', {
      per_page: 100,
      page: current
    })

  if (!response.ok) {
    const problem = getGeneralApiProblem(response)
    if (problem) return problem
  }

  const totalNumberOfPages = Number(response.headers['x-wp-totalpages']);

  try {
    const rawPosts = response.data
    // transform the data into the format we are expecting
    const convertedPosts: PostSnapshotOut[] = rawPosts.map(convertPost)

    allPosts.push(...convertedPosts);

    if (current < totalNumberOfPages) {
      this.getPosts(current + 1, allPosts);
    }

    return {
      kind: "ok",
      posts: allPosts
    }
  } catch (e) {
    console.error(e)
    if (__DEV__) {
      console.tron.error(`Bad data: ${e.message}\n${response.data}`, e.stack)
    }
    return {
      kind: "bad-data"
    }
  }
}
Valerle answered 7/8, 2023 at 0:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.