patricksayshi
patricksayshi

Reputation: 1395

Is file_get_contents() a blocking function?

I am connecting to an unreliable API via file_get_contents. Since it's unreliable, I decided to put the api call into a while loop thusly:

$resultJSON = FALSE;

while(!$resultJSON) {
    $resultJSON = file_get_contents($apiURL);
    set_time_limit(10);
}

Putting it another way: Say the API fails twice before succeeding on the 3rd try. Have I sent 3 requests, or have I sent however many hundreds of requests as will fit into that 3 second window?

Upvotes: 5

Views: 6165

Answers (4)

Jordan Mack
Jordan Mack

Reputation: 8743

Yes, it is a blocking function. You should also check to see if the value is specifically "false". (Note that === is used, not ==.) Lastly, you want to sleep for 10 seconds. set_time_limit() is used to set the max execution time before it is automatically killed.

set_time_limit(300); //Run for up to 5 minutes.

$resultJSON = false;
while($resultJSON === false)
{
    $resultJSON = file_get_contents($apiURL);
    sleep(10);
}

Upvotes: 2

Sammitch
Sammitch

Reputation: 32272

I am not aware of any function in PHP that does not "block". As an alternative, and if your server permits such things, you can:

  1. Use pcntl_fork() and do other stuff in your script while waiting for the API call to go through.
  2. Use exec() to call another script in the background [using &] to do the API call for you if pcntl_fork() is unavailable.

However, if you literally cannot do anything else in your script without a successful call to that API then it doesn't really matter if the call 'blocks' or not. What you should really be concerned about is spending so much time waiting for this API that you exceed the configured max_execution_time and your script is aborted in the middle without being properly completed.

$max_calls = 5;
for( $i=1; $i<=$max_calls; $i++ ) {
    $resultJSON = file_get_contents($apiURL);
    if( $resultJSON !== false ) {
        break;
    } else if( $i = $max_calls ) {
        throw new Exception("Could not reach API within $max_calls requests.");
    }
    usleep(250000); //wait 250ms between attempts
}

It's worth noting that file_get_contents() has a default timeout of 60 seconds so you're really in danger of the script being killed. Give serious consideration to using cURL instead since you can set much more reasonable timeout values.

Upvotes: 1

sierrasdetandil
sierrasdetandil

Reputation: 461

Expanding on @Sammitch suggestion to use cURL instead of file_get_contents():

<?php
$apiURL = 'http://stackoverflow.com/';

$curlh = curl_init($apiURL);
// Use === not ==
// if ($curlh === FALSE) handle error;
curl_setopt($curlh, CURLOPT_FOLLOWLOCATION, TRUE); // maybe, up to you
curl_setopt($curlh, CURLOPT_HEADER, FALSE); // or TRUE, according to your needs
curl_setopt($curlh, CURLOPT_RETURNTRANSFER, TRUE);
// set your timeout in seconds here
curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($curlh, CURLOPT_TIMEOUT, 30);
$resultJSON = curl_exec($curlh);
curl_close($curlh);
// if ($resultJSON === FALSE) handle error;
echo "$resultJSON\n"; // Now process $resultJSON
?>

There are a lot more curl_setopt options. You should check them out.

Of course, this assumes you have cURL available.

Upvotes: 1

user149341
user149341

Reputation:

file_get_contents(), like basically all functions in PHP, is a blocking call.

Upvotes: 9

Related Questions