Как я могу обработать предупреждение функции file_get_contents () в PHP?

312

Я написал такой код PHP

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

Но когда я удаляю "http: //" из $site я получаю следующее предупреждение:

Предупреждение: file_get_contents (www.google.com) [function.file-get-contents]: не удалось открыть поток:

Я попробовал tryи , catchно это не сработало.

Waseem
источник
2
Также интересный подход: stackoverflow.com/questions/6718598/…
Уго Штиглиц
Связанный: stackoverflow.com/q/2002610
Fr0zenFyr
Использование примерки задвижка с set_error_handler-функции , как сказал здесь stackoverflow.com/a/3406181/1046909
MingalevME
2
Если вы удалите http: // из URL, то вы ищете файл "www.google.com" на локальном диске.
Раули Раджанде
Как это может получить так много внимания и голосов. Почему вы удалили информацию протокола? Даже в 2008 году у вас были FTP и HTTPS.
Даниэль В.

Ответы:

507

Шаг 1: проверьте код возврата: if($content === FALSE) { // handle error here... }

Шаг 2: подавить предупреждение, поместив оператор контроля ошибок (т.е. @) перед вызовом file_get_contents () : $content = @file_get_contents($site);

Рул
источник
86
Не забывайте использовать строгое сравнение: если ($ content === FALSE). Если файл содержит «0», то это приведет к ложному отрицанию.
Арам Кочарян
7
Привет, это не сработало для меня, добавление @ по-прежнему приводит к тому, что E_WARNING перехватывается каким-то глобальным (не моим) обработчиком ошибок, и мой сценарий умирает, прежде чем у меня появляется возможность обработать возвращаемое значение. Любые идеи? Тпй.
Саги Манн
1
Обнаружен побочный эффект: если файл не существует, сценарий останавливается в строке @file_get_contents.
Дакс
Это не работает для меня, даже если это будет правильным решением. У меня есть предупреждение о тайм-ауте, данные не получены, но $ content === FALSE не «сработал» ($ site вызывается с локального сервера, обратите внимание, что у меня быстро появляются данные, если я вставляю URL в браузер).
Оливер
4
Хотя ответ очень старый, я все же предлагаю добавить примечание к вашему ответу, которое @может негативно повлиять на производительность. Смотрите этот ответ в соответствующем посте, который объясняет довольно хорошо.
Fr0zenFyr
148

Вы также можете установить свой обработчик ошибок как анонимную функцию, которая вызывает исключение и использовать try / catch для этого исключения.

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

Похоже, много кода, чтобы поймать одну маленькую ошибку, но если вы используете исключения во всем приложении, вам нужно будет сделать это только один раз, вверху (например, во включенном конфигурационном файле), и это будет Преобразуйте все ваши ошибки в исключения.

enobrev
источник
Это одно из величайших улучшений PHP, которое я видел до сих пор. Спасибо enobrev
Томаш Смыковски
@enobrev, почему вы указали одно и то же значение как для номера ошибки, так и для серьезности?
Пейсер
Нет особой причины, кроме возможности предложить что-то полезное в $ exception-> getCode (), поскольку set_error_handler не предлагает переменную с номером ошибки (к сожалению).
enobrev
1
@enobrev Не забудьте восстановить обработчик ошибок внутри анонимной функции перед выдачей исключения. Исключение можно обработать, и в этом случае обработчик по-прежнему настроен на выдачу этого конкретного исключения, которое может быть неожиданным и приводить к странному, трудному для отладки поведению, когда при обработке исключения возникает другая ошибка.
Йозеф Сабл
1
Я бы порекомендовал включить вызов restore_error_handler () в блок finally
Песчанко
67

Мой любимый способ сделать это довольно просто:

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

Я нашел это после экспериментирования с try/catch@enobrev выше, но это учитывает менее длинный (и IMO, более читаемый) код. Мы просто используем, error_get_lastчтобы получить текст последней ошибки, и file_get_contentsвозвращает false при сбое, поэтому простое «если» может это уловить.

Laurie
источник
2
Это самое простое и лучшее решение этой проблемы! Может быть, сделать это, @file_get_contentsчтобы подавить сообщение об ошибке в браузере.
EDP
1
Я допускаю, что среди всех ответов это единственный разумный ответ - если бы мы расширили его, чтобы использовать @file_get_contentsдля подавления предупреждения и проверки значения результата, используя === FALSE.
kostix
11
Это вызовет ошибки для успешных запросов, которые не возвращают тело, или возвращают тот, который оценивается как ложный. Должно бытьif (false !== ($data = file_get_contents ()))
GordonM
Документация не проясняет, но использование @ может привести error_get_lastк тому, что я ничего не
Глен Шмидт,
33

Вы можете добавить @: $content = @file_get_contents($site);

Это подавит любое предупреждение - используйте экономно! , Смотрите Операторы контроля ошибок

Изменить: Когда вы удаляете http: //, вы больше не ищете веб-страницу, а файл на вашем диске под названием "www.google ....."

Greg
источник
Это единственное, что действительно работает - я не мог подавить сообщение «не удалось открыть поток» другим способом.
Олаф
21

Один из вариантов - подавить ошибку, а также вызвать исключение, которое вы можете перехватить позже. Это особенно полезно, если в вашем коде есть несколько вызовов file_get_contents (), так как вам не нужно подавлять и обрабатывать их все вручную. Вместо этого можно сделать несколько вызовов этой функции в одном блоке try / catch.

// 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();
}
Арам Кочарян
источник
15

Вот как я это сделал ... Нет необходимости в блоке try-catch ... Лучшее решение всегда самое простое ... Наслаждайтесь!

$content = @file_get_contents("http://www.google.com");
if (strpos($http_response_header[0], "200")) { 
   echo "SUCCESS";
} else { 
   echo "FAILED";
} 

источник
4
-1: это работает, если вы получаете ошибку 404 или что-то, но не если вы вообще не можете подключиться к серверу (например, неправильное имя домена). Я думаю, что $http_response_headerне обновляется в этом случае, так как не получен ответ HTTP.
Натан Рид
1
Как сказал @NathanReed, вы должны проверить, что $ content не ложно (с ===), поскольку это то, что возвращается, если запрос вообще не соединяется
Seb
15
function custom_file_get_contents($url) {
    return file_get_contents(
        $url,
        false,
        stream_context_create(
            array(
                'http' => array(
                    'ignore_errors' => true
                )
            )
        )
    );
}

$content=FALSE;

if($content=custom_file_get_contents($url)) {
    //play with the result
} else {
    //handle the error
}
RafaSashi
источник
Это не работает Если значение $url404 не найдено, предупреждение все равно появится.
Raptor
Правильный Raptor, я улучшил ответ с помощью stream_context_create (); Ничего лучше ... "@" не рекомендуется
RafaSashi
1
ignore_errorsтолько указывает HTTP-контексту не интерпретировать коды состояния HTTP- ответа> = 400 как ошибки. Хотя и незначительно связаны, это не отвечает на вопрос об обработке ошибок PHP.
вс
Спасибо за ignore_errorsвариант! Это то, что мне было нужно!
Моддер
6

Вот как я справляюсь с этим:

$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();
}
Jrm
источник
4

Лучше всего было бы установить свои собственные обработчики ошибок и исключений, которые будут делать что-то полезное, например, регистрировать его в файле или отправлять по электронной почте критические сообщения. http://www.php.net/set_error_handler


источник
1

Вы могли бы использовать этот скрипт

$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";
}
Ogie
источник
Это требует строгого сравнения: if ($url === true)...потому что, если вы получаете в качестве ответа 0или пусто, это вызывает ошибку соединения.
Даниэль В.
1

Начиная с PHP 4 используйте 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;
}
Боб Стейн
источник
1

Самый простой способ сделать это - просто добавить @ перед file_get_contents, т.е. е .:

$content = @file_get_contents($site); 
Мухаммед Адель Малик
источник
1

что-то вроде этого:

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]);
}
Майкл де Оз
источник
1
if (!file_get_contents($data)) {
  exit('<h1>ERROR MESSAGE</h1>');
} else {
      return file_get_contents($data);
}
Фрэнк Рич
источник
-2

Вы должны использовать функцию file_exists (), прежде чем использовать file_get_contents (). Таким образом вы избежите предупреждения php.

$file = "path/to/file";

if(file_exists($file)){
  $content = file_get_contents($file);
}
Хесус Диас
источник
Это будет работать только в том случае, если вы вызываете локальный файл и у вас есть права на проверку локального файла, если он существует
rubo77
-3

Изменить файл php.ini

allow_url_fopen = On

allow_url_include = On
Антерио Виейра
источник
Не делай этого. Особенно не позволяйте URL-адресам. Не верь мне. По умолчанию он был отключен по очень веской причине # c99.
Даниэль В.
-3

Он попытается получить данные, если они не будут работать, он поймает ошибку и позволит вам сделать все, что вам нужно в рамках перехвата.

try {
    $content = file_get_contents($site);
} catch(\Exception $e) {
    return 'The file was not found';
}
штифтик
источник
-3
try {
   $site="http://www.google.com";
   $content = file_get_content($site);
   echo $content;
} catch (ErrorException $e) {
    // fix the url

}

set_error_handler(function ($errorNumber, $errorText, $errorFile,$errorLine ) 
{
    throw new ErrorException($errorText, 0, $errorNumber, $errorFile, $errorLine);
});
КТА
источник
file_get_content не всегда
выдает
Хотели бы вы отредактировать свой ответ и сообщить нам, в какое время file_get_content генерирует исключения?
Равиндер Паял
1
Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, почему и / или как этот код отвечает на вопрос, повышает его долгосрочную ценность.
Джей Бланшар
-3

Вы также должны установить

allow_url_use = On 

в вашем, php.iniчтобы перестать получать предупреждения.

GHAV
источник