Я написал такой PHP-код
$site = "http://www.google.com";
$content = file_get_content($site);
echo $content;
Но когда я удаляю http: // из $site, я получаю следующее предупреждение:
Warning: file_get_contents(www.google.com) [function.file-get-contents]: failed to open stream:
Я пробовал try и catch, но ничего не вышло.
Связанный: stackoverflow.com/q/2002610
Используйте try-catch с функцией set_error_handler, как сказано здесь stackoverflow.com/a/3406181/1046909
Если вы удалите http: // из url, значит, вы ищете файл www.google.com на вашем локальном диске.
Как это может привлечь столько внимания и голосов? Зачем вам удалять информацию о протоколе. Даже в 2008 году у вас были FTP и HTTPS.






Вы можете добавить @:
$content = @file_get_contents($site);
Это подавит любое предупреждение - используйте экономно!. См. Операторы контроля ошибок
Обновлено: когда вы удаляете http: //, вы больше ищете не веб-страницу, а файл на вашем диске под названием «www.google .....»
Это единственное, что действительно работает - я не мог каким-либо другим способом подавить сообщение «Не удалось открыть поток».
Шаг 1: проверьте код возврата: if ($content === FALSE) { // handle error here... }
Шаг 2: подавите предупреждение, поместив оператор контроля ошибок (т.е. @) перед вызовом file_get_contents ():
$content = @file_get_contents($site);
Не забудьте использовать строгое сравнение: if ($ content === FALSE). Если файл содержит «0», то это вызовет ложноотрицательный результат.
Привет, это не сработало для меня, добавление @ по-прежнему приводит к тому, что E_WARNING перехватывается каким-то глобальным (не моим) обработчиком ошибок, и мой скрипт умирает, прежде чем у меня будет возможность обработать возвращаемое значение. Есть идеи? tnx.
Обнаружен побочный эффект: если файл не существует, сценарий останавливается на строке @file_get_contents.
Это не работает для меня, даже если это будет правильное решение. У меня есть предупреждение о тайм-ауте без получения данных, но $ content === FALSE не "запускается" ($ site вызывается с сервера localhost, обратите внимание, что у меня есть данные быстро, если я вставляю URL-адрес в браузер).
Хотя ответ очень старый, я все же предлагаю добавить к вашему ответу примечание о том, что использование @ может отрицательно сказаться на производительности. См. этот ответ в соответствующей публикации, которая довольно хорошо объясняет.
@ Fr0zenFyr Есть ли у вас какие-либо данные о производительности, подтверждающие вашу претензию?
И как узнать, в чем была настоящая ошибка? errno из локальной операции или код состояния HTTP из удаленного?
Пожалуйста, @file_get_contents работает, но это ужасная практика. Гораздо правильнее решение с обработчиком ошибок. Избегайте этого решения.
не делай этого. Вы просто подавляете предупреждение об ошибке. это не обработка ошибок! это создаст проблемы при отладке.
Лучше всего было бы установить свои собственные обработчики ошибок и исключений, которые будут делать что-то полезное, например, регистрировать их в файле или отправлять по электронной почте важные. http://www.php.net/set_error_handler
Вот как я это сделал ... Нет необходимости в блоке try-catch ... Лучшее решение - всегда самое простое ... Наслаждайтесь!
$content = @file_get_contents("http://www.google.com");
if (strpos($http_response_header[0], "200")) {
echo "SUCCESS";
} else {
echo "FAILED";
}
-1: это работает, если вы получаете ошибку 404 или что-то в этом роде, но не если вы вообще не можете подключиться к серверу (например, неправильное доменное имя). Я думаю, что $http_response_header в этом случае не обновляется, так как HTTP-ответ не получен.
Как сказал @NathanReed, вы должны проверить, что $ content не является ложным (с ===), поскольку это то, что возвращается, если запрос вообще не может подключиться
Вы также можете установите свой обработчик ошибок как анонимная функция, который вызывает Исключение и использовать 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, почему вы ставите одинаковое значение и для номера ошибки, и для серьезности?
Нет особой причины, кроме возможности предложить что-то полезное в $ exception-> getCode (), поскольку set_error_handler не предлагает переменную номера ошибки (к сожалению).
Думаю, это может быть более верный ответ для PHP5.
У меня есть предупреждение о тайм-ауте, которое не улавливается таким образом
Может кто-нибудь объяснить мне, почему для этого недостаточно простого улова?
@lolka_bolka, потому что file_get_contents не генерирует исключение, а вместо этого выдает ошибку php. Итак, в этом примере настраивается «обработчик ошибок», который улавливает большинство экземпляров возникающих ошибок php и вместо этого преобразует эти ошибки в исключения. Вот более современный пример из документации: php.net/manual/en/…
Это единственный правильный ответ, потому что при использовании @file_get_contents PHP все еще отправляет ошибку в stderr, затем идет журнал ошибок nginx: 2017/02/09 15:00:17 [ошибка] 4982 # 0: * 16548967 FastCGI отправлено в stderr: «Сообщение PHP: предупреждение PHP: file_get_contents (SOME_MY_URL): не удалось открыть поток: сбой HTTP-запроса! HTTP / 1.1 404 не найден в /path/to/public/index.php в строке 15», клиент: 10.24.1.36, сервер : my-server1, запрос: «GET SOME_MY_URL HTTP / 1.1», хост: «MY_HOST»
@enobrev Не забудьте восстановить обработчик ошибок внутри анонимной функции перед выдачей исключения. Исключение может быть обработано, и в этом случае обработчик по-прежнему настроен на выдачу этого конкретного исключения, которое может быть неожиданным и привести к странному, трудно поддающемуся отладке поведению при возникновении другой ошибки в обработке исключения.
Я бы рекомендовал включить вызов restore_error_handler () в блок finally
Одна альтернатива - подавить ошибку, а также выбросить исключение, которое вы можете поймать позже. Это особенно полезно, если в вашем коде есть несколько вызовов 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();
}
Вы можете использовать этот скрипт
$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";
}
Это требует строгого сравнения: if ($url === true)..., потому что, если вы получите в качестве ответа 0 или пустой, это приведет к ошибке соединения.
Мой любимый способ сделать это довольно просто:
if (false !== ($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 в случае ошибки, так что простое «если» может это уловить.
Это самое простое и лучшее решение этой проблемы! Может быть, сделать это @file_get_contents, чтобы подавить сообщение об ошибке браузеру.
Я признаю, что среди всех ответов это единственный разумный - если бы мы расширили его, чтобы использовать @file_get_contents для подавления предупреждения и, проверьте значение результата с помощью === FALSE.
Это вызовет ошибки для успешных запросов, которые не возвращают тело или возвращают значение false. Должен быть if (false !== ($data = file_get_contents ()))
В документации это не проясняется, но, по моему опыту, использование @ может привести к тому, что error_get_last ничего не вернет.
Первое условие - обратное. Если false не совпадает с результатом вызова file_get_contents, значит, он получил некоторое содержимое, и нам не следует искать ошибку. Я был сбит с толку, увидев ошибки из предыдущего теста или ошибку, что $ error имеет значение null, когда Google действительно был найден!
Вот как я с этим справляюсь:
$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();
}
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
}
Это не работает. Если $url 404 не найден, предупреждение все равно появится.
Правильный Raptor, я улучшил ответ с помощью stream_context_create (); Ничего лучше ... "@" не рекомендуется
ignore_errors только указывает контексту HTTP не интерпретировать коды состояния ответа HTTP> = 400 как ошибки. Хотя это незначительно связано, это не отвечает на вопрос об обработке ошибок PHP.
Спасибо за вариант ignore_errors! Это то, что мне было нужно!
Поскольку PHP 4 использует Отчет об ошибках():
$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;
}
Измените файл php.ini
allow_url_fopen = On
allow_url_include = On
Не делай этого. Особенно не допускайте включения URL. Не надо, поверь мне. По умолчанию он отключен по очень веской причине # c99.
Вы также должны установить
allow_url_use = On
в вашем php.ini, чтобы перестать получать предупреждения.
Он попытается получить данные, если это не сработает, оно перехватит ошибку и позволит вам сделать все, что вам нужно, в пределах перехвата.
try {
$content = file_get_contents($site);
} catch(\Exception $e) {
return 'The file was not found';
}
Вы должны использовать функцию file_exists (), прежде чем использовать file_get_contents (). Таким образом вы избежите предупреждения php.
$file = "path/to/file";
if (file_exists($file)){
$content = file_get_contents($file);
}
Это будет работать, только если вы вызовете локальный файл и у вас есть права на проверку локального файла, если он существует.
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 выдает исключения?
Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, почему и / или как этот код отвечает на вопрос, улучшает его долгосрочную ценность.
Самый простой способ сделать это - просто добавить @ перед file_get_contents, i. e .:
$content = @file_get_contents($site);
что-то вроде этого:
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]);
}
if (!file_get_contents($data)) {
exit('<h1>ERROR MESSAGE</h1>');
} else {
return file_get_contents($data);
}
нет. вы должны === для проверки условий. не ==
Не рекомендую запускать file_get_contents дважды. Достаточно один раз.
Включите allow_url_fopen из cPanel или WHM, затем попробуйте, надеюсь, это исправит
Тоже интересный подход: stackoverflow.com/questions/6718598/…