365

I wrote a PHP code like this

$site="http://www.google.com";
$content = file_get_content($site);
echo $content;

But when I remove "http://" from $site I get the following warning:

Warning: file_get_contents(www.google.com) [function.file-get-contents]: failed to open stream:

I tried try and catch but it didn't work.

Paulo Boaventura
  • 1,365
  • 1
  • 9
  • 29
Waseem
  • 11,741
  • 15
  • 41
  • 45

17 Answers17

589

Step 1: check the return code: if($content === FALSE) { // handle error here... }

Step 2: suppress the warning by putting an error control operator (i.e. @) in front of the call to file_get_contents(): $content = @file_get_contents($site);

Sᴀᴍ Onᴇᴌᴀ
  • 8,218
  • 8
  • 36
  • 58
Roel
  • 19,338
  • 6
  • 61
  • 90
  • 102
    Remember to use strict comparison: if ($content === FALSE) .If the file contains "0", then it will trigger a false negative. – Aram Kocharyan Jun 24 '11 at 03:48
  • 8
    Hi, this didn't work for me, adding @ still causes E_WARNING to be caught by some global (not mine) error handler, and my script dies before I have a chance to handle the return value. Any ideas? tnx. – Sagi Mann Nov 22 '12 at 06:51
  • 2
    Side effect detected: if the file does not exist, the script stops at the @file_get_contents line. – Dax Dec 23 '12 at 13:42
  • This does not work for me, even if this is about to be the right solution. I have a timeout warning with no data received, but $content === FALSE is not "triggered" ($site being called from a localhost server, note that I have datas quickly if I paste myself the url into a browser). – Oliver Dec 24 '14 at 12:39
  • 5
    Though the answer is very old, I still suggest adding a note to your answer that using `@` may negatively impact performance. See [this answer](http://stackoverflow.com/a/2002789/1369473) on a related post that explains fairly well. – Fr0zenFyr Jun 30 '15 at 19:35
  • @Fr0zenFyr Do you have any performance data to back your claim? – Sven Jun 06 '16 at 15:09
  • And how do get, what the actual error was? The `errno` from a local operation, or the HTTP status code from a remote? – Mikhail T. May 16 '17 at 20:03
  • Please, @file_get_contents works but it's a terrible practice. The solution with the error handler is much more proper. Avoid that solution. – Raphaël Gonçalves Dec 11 '17 at 10:44
  • 5
    don't do this. You just surpress the error warning. this is no error handling! this will make problems in debugging. – helle Jul 15 '19 at 08:56
  • Now that's the kind of the answer for which we all hate Stack Overflow so much. Not a bit of handling but just blunt error suppression – Your Common Sense Jun 17 '22 at 07:48
177

You can also set your error handler as an anonymous function that calls an Exception and use a try / catch on that exception.

set_error_handler(
    function ($severity, $message, $file, $line) {
        throw new ErrorException($message, $severity, $severity, $file, $line);
    }
);

try {
    file_get_contents('www.google.com');
}
catch (Exception $e) {
    echo $e->getMessage();
}

restore_error_handler();

Seems like a lot of code to catch one little error, but if you're using exceptions throughout your app, you would only need to do this once, way at the top (in an included config file, for instance), and it will convert all your errors to Exceptions throughout.

enobrev
  • 22,314
  • 7
  • 42
  • 53
  • @enobrev, Why do you put the same value for both error number and severity? – Pacerier Jul 16 '13 at 18:38
  • No specific reason besides a means of offering something useful in $exception->getCode(), since set_error_handler does not offer an error number variable (unfortunately). – enobrev Jul 16 '13 at 19:42
  • Think this might be the more valid answer for PHP5. – James P. Sep 29 '13 at 20:52
  • I have a timeout warning that is not catched this way – Oliver Dec 24 '14 at 12:44
  • Can somebody explain me, why a simple try - catch isn't enough for it? – vaso123 Oct 01 '15 at 13:48
  • 2
    @lolka_bolka because file_get_contents doesn't throw an exception, but instead throws a php error. So what this example does is sets up an "error handler" that catches most instances of php errors being thrown and instead converts those errors to exceptions. Here's a more modern example from the docs: http://php.net/manual/en/class.errorexception.php#errorexception.examples – enobrev Oct 01 '15 at 17:23
  • This is the only right answer because when @file_get_contents is used the PHP still send error to stderr, next is nginx error log: 2017/02/09 15:00:17 [error] 4982#0: *16548967 FastCGI sent in stderr: "PHP message: PHP Warning: file_get_contents(SOME_MY_URL): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in /path/to/public/index.php on line 15", client: 10.24.1.36, server: my-server1, request: "GET SOME_MY_URL HTTP/1.1", host: "MY_HOST" – MingalevME Feb 09 '17 at 12:02
  • 2
    @enobrev Don't forget to restore error handler inside anonymous function before throwing exception. Exception can be handled and in that case the handler is still set to throw this particular exception which may come as unexpected and introduce weird, hard to debug, behavior when there is another error in exception handling. – Josef Sábl Oct 23 '17 at 08:57
  • 2
    I would recommend to include restore_error_handler() call in finally block – peschanko Apr 07 '19 at 10:00
  • It's super irritating that these kinds of errors are warnings in the first place. ESP in my situation of writing to a file, if I cant write to the file it should be an error, I shouldn't be forced to escalate it manually just to see if its a permission issue vs a bad directory path. – Brad Apr 12 '21 at 04:52
114

My favorite way to do this is fairly simple:

if (($data = @file_get_contents("http://www.google.com")) === false) {
      $error = error_get_last();
      echo "HTTP request failed. Error was: " . $error['message'];
} else {
      echo "Everything went better than expected";
}

I found this after experimenting with the try/catch from @enobrev above, but this allows for less lengthy (and IMO, more readable) code. We simply use error_get_last to get the text of the last error, and file_get_contents returns false on failure, so a simple "if" can catch that.

Garland Pope
  • 3,242
  • 1
  • 25
  • 19
Laurie
  • 1,173
  • 1
  • 7
  • 4
  • 2
    This is the easiest and best solution for this problem! Maybe make it `@file_get_contents` to supress the error reporting to the browser. – EDP Dec 30 '15 at 08:36
  • 1
    I admit that among all the answers this is the only sensible one -- if we'd augment it to use `@file_get_contents` to suppress the warning ***and*** test the result value using `=== FALSE`. – kostix Feb 10 '16 at 13:01
  • 13
    This will trigger errors for successful requests that don't return a body, or return one that evaluates to false. Should be `if (false !== ($data = file_get_contents ()))` – GordonM Jun 06 '16 at 09:49
  • The documentation doesn't make it clear, but using @ can cause `error_get_last` to return nothing in my experience – Glenn Schmidt Jan 30 '17 at 07:49
  • 3
    The first condition is backwards. If false does not equal the result of the file_get_contents call then it got some contents and we should not be looking for an error. I was confused in seeing errors from the previous test or seeing an error that $error was null when google really was found! – Robert Jan 23 '21 at 17:15
  • I have updated the answer to include the feedback in prior comments. – Garland Pope Aug 17 '21 at 02:05
42

You can prepend an @: $content = @file_get_contents($site);

This will supress any warning - use sparingly!. See Error Control Operators

Edit: When you remove the 'http://' you're no longer looking for a web page, but a file on your disk called "www.google....."

Greg
  • 316,276
  • 54
  • 369
  • 333
  • That's the only thing that really works - I could not suppress the "failed to open stream" message any other way. – Olaf Sep 25 '17 at 13:06
26

One alternative is to suppress the error and also throw an exception which you can catch later. This is especially useful if there are multiple calls to file_get_contents() in your code, since you don't need to suppress and handle all of them manually. Instead, several calls can be made to this function in a single try/catch block.

// Returns the contents of a file
function file_contents($path) {
    $str = @file_get_contents($path);
    if ($str === FALSE) {
        throw new Exception("Cannot access '$path' to read contents.");
    } else {
        return $str;
    }
}

// Example
try {
    file_contents("a");
    file_contents("b");
    file_contents("c");
} catch (Exception $e) {
    // Deal with it.
    echo "Error: " , $e->getMessage();
}
Aram Kocharyan
  • 20,165
  • 11
  • 81
  • 96
19
function custom_file_get_contents($url) {
    
    return file_get_contents(
        $url,
        false,
        stream_context_create(
            array(
                'http' => array(
                    'ignore_errors' => true
                )
            )
        )
    );
}


if( $content = custom_file_get_contents($url) ) {

    //play with the result

} 
else {

    //handle the error
}
RafaSashi
  • 16,483
  • 8
  • 84
  • 94
  • This doesn't work. If the `$url` is 404 not found, warning will still appear. – Raptor May 16 '14 at 03:16
  • Right Raptor, I have improved the answer with stream_context_create(); Nothing better... "@" not recommended – RafaSashi May 16 '14 at 14:23
  • 1
    [`ignore_errors`](http://php.net/manual/en/context.http.php#context.http.ignore-errors) only instructs the HTTP context to not interpret **HTTP** response status codes >= 400 as errors. While marginally related, that does not answer the question of PHP error handling. – sun Jul 01 '14 at 16:51
  • 1
    Thanks for `ignore_errors` option! This is what I needed! – Modder Feb 16 '20 at 17:25
16

Here's how I did it... No need for try-catch block... The best solution is always the simplest... Enjoy!

$content = @file_get_contents("http://www.google.com");
if (strpos($http_response_header[0], "200")) { 
   echo "SUCCESS";
} else { 
   echo "FAILED";
} 
  • 5
    -1: this works if you get a 404 error or something, but not if you fail to connect to the server at all (e.g. wrong domain name). I think `$http_response_header` is not updated in that case, since no HTTP response is received. – Nathan Reed Mar 24 '13 at 01:50
  • 1
    As @NathanReed said, you should check $content is not false (with ===) as that's what gets return if the request fails to connect at all – Seb Jan 20 '14 at 09:25
6

Here's how I handle that:

$this->response_body = @file_get_contents($this->url, false, $context);
if ($this->response_body === false) {
    $error = error_get_last();
    $error = explode(': ', $error['message']);
    $error = trim($error[2]) . PHP_EOL;
    fprintf(STDERR, 'Error: '. $error);
    die();
}
Barry
  • 3,303
  • 7
  • 23
  • 42
Jrm
  • 149
  • 2
  • 1
5

The best thing would be to set your own error and exception handlers which will do something usefull like logging it in a file or emailing critical ones. http://www.php.net/set_error_handler

0

Since PHP 4 use error_reporting():

$site="http://www.google.com";
$old_error_reporting = error_reporting(E_ALL ^ E_WARNING);
$content = file_get_content($site);
error_reporting($old_error_reporting);
if ($content === FALSE) {
    echo "Error getting '$site'";
} else {
    echo $content;
}
Bob Stein
  • 16,271
  • 10
  • 88
  • 101
-1

something like this:

public function get($curl,$options){
    $context = stream_context_create($options);
    $file = @file_get_contents($curl, false, $context);
    $str1=$str2=$status=null;
    sscanf($http_response_header[0] ,'%s %d %s', $str1,$status, $str2);
    if($status==200)
        return $file        
    else 
        throw new \Exception($http_response_header[0]);
}
Laurenz Albe
  • 209,280
  • 17
  • 206
  • 263
-2

You should use file_exists() function before to use file_get_contents(). With this way you'll avoid the php warning.

$file = "path/to/file";

if(file_exists($file)){
  $content = file_get_contents($file);
}
Jesús Díaz
  • 362
  • 4
  • 5
  • 2
    This would only work, if you call a local file and you have the right permissions to check the local file if it exists – rubo77 Jan 30 '18 at 11:05
-2

Simplest way to do this is just prepend an @ before file_get_contents, i. e.:

$content = @file_get_contents($site); 
Armali
  • 18,255
  • 14
  • 57
  • 171
-2

I was resolve all problem, it's work all links

public function getTitle($url)
    {
        try {
            if (strpos($url, 'www.youtube.com/watch') !== false) {
                $apikey = 'AIzaSyCPeA3MlMPeT1CU18NHfJawWAx18VoowOY';
                $videoId = explode('&', explode("=", $url)[1])[0];
                $url = 'https://www.googleapis.com/youtube/v3/videos?id=' . $videoId . '&key=' . $apikey . '&part=snippet';

                $ch = curl_init();

                curl_setopt($ch, CURLOPT_HEADER, 0);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                curl_setopt($ch, CURLOPT_URL, $url);
                curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
                curl_setopt($ch, CURLOPT_VERBOSE, 0);
                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
                $response = curl_exec($ch);
                curl_close($ch);

                $data = json_decode($response);
                $value = json_decode(json_encode($data), true);

                $title = $value['items'][0]['snippet']['title'];
            } else {
                set_error_handler(
                    function () {
                            return false;
                    }
                );
                if (($str = file_get_contents($url)) === false) {
                    $title = $url;
                } else {
                    preg_match("/\<title\>(.*)\<\/title\>/i", $str, $title);
                    $title = $title[1];
                    if (preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $title))
                        $title = utf8_encode($title);
                    $title = html_entity_decode($title);
                }
                restore_error_handler();
            }
        } catch (Exception $e) {
            $title = $url;
        }
        return $title;
    }
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 09 '21 at 09:31
-2

You could use this script

$url = @file_get_contents("http://www.itreb.info");
if ($url) {
    // if url is true execute this 
    echo $url;
} else {
    // if not exceute this 
    echo "connection error";
}
Jeffrey
  • 1,239
  • 8
  • 15
ogie
  • 5
  • 1
  • This needs strict comparison: `if ($url === true)...` because if you get as a response `0` or empty, it raises connection error. – Daniel W. Mar 13 '18 at 13:00
-4

This will try to get the data, if it does not work, it will catch the error and allow you to do anything you need within the catch.

try {
    $content = file_get_contents($site);
} catch(\Exception $e) {
    return 'The file was not found';
}
Brad
  • 12,054
  • 44
  • 118
  • 187
-4
if (!file_get_contents($data)) {
  exit('<h1>ERROR MESSAGE</h1>');
} else {
      return file_get_contents($data);
}
Frank Rich
  • 13
  • 2