Why does Instagram's pagination return the same page over and over?

903 Views Asked by At

The Code

I've created a PHP class to communicate with Instagram's API. I am using a private function called api_request (shown below) to communicate with Instagram's API:

private function api_request( $request = null ) {

    if ( is_null( $request ) ) {
        $request = $this->request["httpRequest"];
    }
    $body = wp_remote_retrieve_body( wp_remote_get( $request, array(
                "timeout" => 10,
                "content-type" => "application/json"
            )
        )
    );

    try {
        $response = json_decode( $body, true );
        $this->data["pagination"] = $response["pagination"]["next_url"];
        $this->data["response"] = $response["data"];

        $this->setup_data( $this->data );

    } catch ( Exception $ex ) {
        $this->data = null;
    }
}

These two lines of code...

$this->data["pagination"] = $response["pagination"]["next_url"];
$this->data["response"] = $response["data"];

...sets up my data within this array:

private $data = array (
    "response"      => null,
    "pagination"    => null,
    "photos"        => array()
);

The Problem

Whenever I request the next page, with the following function:

public function pagination_query() {
    $this->api_request( $this->data["pagination"] );
    $output = json_encode( $this->data["photos"] );

    return $output;
}

Instagram gives me the first page, over and over and over gain. Any idea what the problem is here?

Update #1

I realized that because my setup_data function (used in api_request function) pushes my photo objects onto the end of my $this->data["photos"] array:

private function setup_data( $data ) {

    foreach ( $data["response"] as $obj ) {

        /* code that parses the api, goes here */


        /* pushes new object onto photo stack */
        array_push( $this->data["photos"], $new_obj );
    }
}

...it is necessary to create an empty array, when requesting a new page:

public function pagination_query() {

    $this->data["photos"] = array(); // kicks out old photo objects

    $this->api_request( $this->data["pagination"] );
    $output = json_encode( $this->data["photos"] );

    return $output;
}

I'm able to retrieve the second page but all subsequent pagination_query calls only return the second page. Any ideas what could be wrong?

Update #2

I discovered that using a while statement, to make the api_request function call itself, allows to me retrieve page after page just fine:

private function api_request( $request = null ) {

    if ( is_null( $request ) ) {
        $request = $this->request["httpRequest"];
    }

    $body = wp_remote_retrieve_body( wp_remote_get( $request, array(
                "timeout" => 18,
                "content-type" => "application/json"
            )
        )
    );

    try {
        $response = json_decode( $body, true );

        $this->data["response"] = $response["data"];
        $this->data["next_page"] = $response["pagination"]["next_url"];

        $this->setup_data( $this->data );

        // while state returns page after page just fine
        while ( count( $this->data["photos"] ) < 80 ) {
            $this-> api_request( $this->data["next_page"] );
        }

    } catch ( Exception $ex ) {
        $this->data = null;
    }
}

However, this doesn't fix my pagination_query function and it appears as if my try-catch block is creating a closure and I'm not really sure what to make of this.

2

There are 2 best solutions below

5
On

In your first snippet of code you have:

    $this->data["response"] = $response["data"];
    $this->data["next_page"] = $response["pagination"]["next_url"];

Note two keys: response and next_page

Then in your second snippet you have:

    $this->data["pagination"] = $response["pagination"]["next_url"];
    $this->data["response"] = $response["data"];

Now next_page is pagination

Now if you use

$this->api_request( $this->data["pagination"] );

But you are using $this->data["next_page"] = $response["pagination"]["next_url"]; of course you will not get the right results.

In any case try to var_dump the content of of your $request:

public function pagination_query() {
    var_dump($this->data["pagination"]);
    $this->api_request( $this->data["pagination"] );
    $output = json_encode( $this->data["photos"] );

    return $output;
}

If you have a debbugger also check inside api_request which is the url passed each time

0
On

I've added the following lines of code to the try block of my try...catch statement to return several successive pages at a time:

while ( count( $this->data["photos"] ) < 160 ) {
    $this-> api_request( $this->data["next_page"] );
}

This essentially tells api_request to call itself until my $this->data["next_page"] array is populated with 160 "grams."

This allows me retrieve a total of 320 grams from Instagram's api: 160 grams when api_request is called after page load and another 160 from my first pagination_query call.

This isn't an ideal solution as a second pagination_query call still returns the same data from my first pagination_query call but it will have to do for the time being.

Update

The above solution is a hack. If anyone can figure out why my pagination_query method still isn't working, it would be much appreciated.