How can I handle the warning of file_get_contents() function in PHP? [duplicate]
Asked Answered
L

17

371

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.

Latterll answered 7/11, 2008 at 15:10 Comment(5)
Also an interesting approach: #6719098Rudolfrudolfo
Related: https://mcmap.net/q/56229/-character-before-a-function-callZeitler
Use try-catch with set_error_handler-function as said here https://mcmap.net/q/55170/-how-can-i-handle-the-warning-of-file_get_contents-function-in-php-duplicateTravertine
If you remove http:// from url, then you are looking for a file "www.google.com" on your local disk.Arequipa
How can this get so much attention and upvotes. Why would you remove the protocol information. Even in 2008, you had FTP and HTTPS.Befuddle
H
592

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);

Hammy answered 7/11, 2008 at 15:14 Comment(10)
Remember to use strict comparison: if ($content === FALSE) .If the file contains "0", then it will trigger a false negative.Kitsch
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.Pomeroy
Side effect detected: if the file does not exist, the script stops at the @file_get_contents line.Ophelia
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).Uno
Though the answer is very old, I still suggest adding a note to your answer that using @ may negatively impact performance. See this answer on a related post that explains fairly well.Zeitler
@Zeitler Do you have any performance data to back your claim?Marilynnmarimba
And how do get, what the actual error was? The errno from a local operation, or the HTTP status code from a remote?Serigraph
Please, @file_get_contents works but it's a terrible practice. The solution with the error handler is much more proper. Avoid that solution.Pippin
don't do this. You just surpress the error warning. this is no error handling! this will make problems in debugging.Outstanding
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 suppressionJennajenne
Q
180

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.

Quisling answered 4/8, 2010 at 13:51 Comment(10)
@enobrev, Why do you put the same value for both error number and severity?Charlena
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).Quisling
Think this might be the more valid answer for PHP5.Countable
I have a timeout warning that is not catched this wayUno
Can somebody explain me, why a simple try - catch isn't enough for it?Naughton
@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: php.net/manual/en/…Quisling
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"Travertine
@Quisling 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.Jedjedd
I would recommend to include restore_error_handler() call in finally blockChiliad
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.Gokey
J
117

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.

Jesselyn answered 13/11, 2012 at 17:6 Comment(6)
This is the easiest and best solution for this problem! Maybe make it @file_get_contents to supress the error reporting to the browser.Gunter
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.Mauritius
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 ()))Nunciata
The documentation doesn't make it clear, but using @ can cause error_get_last to return nothing in my experienceBrom
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!Prescott
I have updated the answer to include the feedback in prior comments.Barter
P
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....."

Panaggio answered 7/11, 2008 at 15:13 Comment(1)
That's the only thing that really works - I could not suppress the "failed to open stream" message any other way.Randle
K
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();
}
Kitsch answered 24/6, 2011 at 4:17 Comment(0)
O
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
}
Octane answered 24/2, 2014 at 0:28 Comment(4)
This doesn't work. If the $url is 404 not found, warning will still appear.Underclay
Right Raptor, I have improved the answer with stream_context_create(); Nothing better... "@" not recommendedOctane
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.Yu
Thanks for ignore_errors option! This is what I needed!Besotted
H
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";
} 
Houlberg answered 6/3, 2009 at 5:11 Comment(2)
-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.Benildis
As @NathanReed said, you should check $content is not false (with ===) as that's what gets return if the request fails to connect at allGorham
D
7

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();
}
Detritus answered 24/2, 2014 at 0:5 Comment(0)
B
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

Briar answered 7/11, 2008 at 16:57 Comment(0)
W
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;
}
Wamble answered 18/7, 2014 at 18:1 Comment(0)
P
-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]);
}
Psychogenic answered 23/4, 2019 at 16:36 Comment(0)
G
-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";
}
Gerah answered 27/2, 2012 at 7:57 Comment(1)
This needs strict comparison: if ($url === true)... because if you get as a response 0 or empty, it raises connection error.Befuddle
D
-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);
}
Degust answered 3/10, 2016 at 18:18 Comment(1)
This would only work, if you call a local file and you have the right permissions to check the local file if it existsLinguist
K
-2

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

$content = @file_get_contents($site); 
Kaslik answered 8/2, 2019 at 7:56 Comment(0)
I
-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;
    }
Idoux answered 9/10, 2021 at 9:12 Comment(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.Nolita
G
-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';
}
Gokey answered 28/7, 2016 at 16:37 Comment(0)
C
-5
if (!file_get_contents($data)) {
  exit('<h1>ERROR MESSAGE</h1>');
} else {
      return file_get_contents($data);
}
Cinda answered 17/2, 2020 at 3:18 Comment(2)
no. you should you === for condition checking. not ==Raimes
Wouldn't recommend running file_get_contents twice. Once is enough.Pipette

© 2022 - 2024 — McMap. All rights reserved.