Як я можу обробляти попередження про функцію 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-content]: не вдалося відкрити потік:

Я спробував tryі , catchале це не спрацювало.


2
Також цікавий підхід: stackoverflow.com/questions/6718598/…
Hugo Stieglitz

Пов'язаний: stackoverflow.com/q/2002610
Fr0zenFyr

Використовуйте спробу-catch з set_error_handler-функцією, як сказано тут, stackoverflow.com/a/3406181/1046909
MingalevME

2
Якщо ви видалите http: // з URL-адреси, тоді ви шукаєте файл "www.google.com" на локальному диску.
Rauli Rajande

Як можна отримати так багато уваги та нагород. Чому б ви видалили інформацію про протокол. Навіть у 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 був захоплений деяким глобальним (не моїм) обробником помилок, і мій сценарій відмирає, перш ніж у мене з’явиться шанс обробити повернене значення. Будь-які ідеї? tnx.
Сагі Манн

1
Виявлено побічний ефект: якщо файл не існує, скрипт зупиняється на рядку @file_get_contents.
Дакс

Це не працює для мене, навіть якщо це буде правильне рішення. У мене є попередження про час очікування без отриманих даних, але $ content === FALSE не "спрацьовує" (виклик $ сайту з локального сервера, зауважте, що у мене є дані швидко, якщо я вставляю URL-адресу у браузер).
Олівер

4
Хоча відповідь дуже стара, я все ж пропоную додати у відповідь примітку, що використання @може негативно вплинути на ефективність роботи. Дивіться цю відповідь у пов’язаній публікації, яка досить добре пояснює.
Fr0zenFyr

148

Ви також можете встановити обробник помилок як анонімну функцію, яка викликає виняток і використовує спробу / ловити за цим винятком.

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

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


Це одне з найбільших поліпшень PHP, які я бачив досі. Дякую Енобрев
Томаш Смиковський

@enobrev, Чому ви ставите однакове значення як для кількості помилок, так і для суворості?
Pacerier

Окрім способу запропонувати щось корисне в $ изключення-> getCode (), немає жодної конкретної причини, оскільки set_error_handler не пропонує змінну числа помилок (на жаль).
enobrev

1
@enobrev Не забудьте відновити обробник помилок в анонімній функції перед тим, як викинути виняток. Виняток може бути оброблений, і в такому випадку обробник все ще налаштований викинути саме цей виняток, який може стати несподіваним і ввести дивну, важку для налагодження поведінку, коли є інша помилка в обробці винятків.
Йозеф Сабл

1
Я б порекомендував включити заклик
Resto_error_handler

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повертаємо помилку при відмові, тому просте "якщо" може це зрозуміти.


2
Це найпростіше і найкраще рішення цієї проблеми! Можливо, зробити так, @file_get_contentsщоб придушити повідомлення про помилку в браузері.
EDP

1
Я визнаю, що серед усіх відповідей це єдиний розумний - якби ми доповнили його, щоб використовувати @file_get_contentsдля придушення попередження і перевірити значення результату, використовуючи === FALSE.
kostix

11
Це призведе до помилок для успішних запитів, які не повертають тіло, або повертають той, який оцінюється як хибний. Має бутиif (false !== ($data = file_get_contents ()))
GordonM

Документація не дає зрозуміти, але використання @ може призвести error_get_lastдо того, що я нічого не повернув
Glenn Schmidt

33

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

Це придушить будь-яке попередження - використовуйте економно! . Див. Оператори контролю помилок

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


Це єдине, що дійсно працює - я не зміг придушити повідомлення "не вдалося відкрити потік" іншим способом.
Олаф

21

Одна з альтернатив - придушити помилку, а також викинути виняток, який ви можете пізніше пізнати. Це особливо корисно, якщо у вашому коді є кілька дзвінків на файл_get_contents (), оскільки вам не потрібно придушувати та обробляти їх усі вручну. Натомість до цієї функції можна здійснити декілька викликів у одному блоці спробу / лову.

// 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

Ось як я це зробив ... Немає потреби у блоці спробу-лову ... Найкраще рішення завжди найпростіше ... Насолоджуйтесь!

$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, ви повинні перевірити $ зміст перестав бути хибним (з ===) , як це те, що отримує повернення , якщо запит не вдається підключитися взагалі
Себ

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
}

Це не працює. Якщо значення $url404 не знайдено, попередження все одно з’явиться.
Раптор

Правий 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();
}

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";
}

Це потребує суворого порівняння: 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

щось на зразок цього:

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


-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 не завжди кидає виняток
1717 року

Ви хочете відредагувати свою відповідь і сказати нам, що в який момент файл_get_content видає винятки?
Ревіндер Пайал

1
Хоча цей код може відповісти на питання, надаючи додатковий контекст щодо того, чому та / або як цей код відповідає на питання, покращує його довгострокове значення.
Джей Бланшард

-3

Ви також повинні встановити

allow_url_use = On 

у вашому, php.iniщоб припинити отримувати попередження.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.