Jak poradzić sobie z ostrzeżeniem o funkcji file_get_contents () w PHP?


312

Napisałem taki kod PHP

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

Ale kiedy usuwam „http: //” z, pojawia $sitesię następujące ostrzeżenie:

Ostrzeżenie: file_get_contents (www.google.com) [function.file-get-content]: nie można otworzyć strumienia:

Próbowałem tryi catchale to nie działa.


2
Również interesujące podejście: stackoverflow.com/questions/6718598/...
Hugo Stieglitz,


Użyj try-catch z funkcją set_error_handler, jak powiedziano tutaj stackoverflow.com/a/3406181/1046909
MingalevME

2
Jeśli usuniesz http: // z adresu URL, to szukasz pliku „www.google.com” na dysku lokalnym.
Rauli Rajande

Jak to może zyskać tyle uwagi i entuzjazmu. Dlaczego miałbyś usunąć informacje o protokole. Nawet w 2008 roku miałeś FTP i HTTPS.
Daniel W.

Odpowiedzi:


507

Krok 1: Sprawdź kod powrotu: if($content === FALSE) { // handle error here... }

Krok 2: Pomiń ostrzeżenie, umieszczając operator kontroli błędów (tj. @) Przed wywołaniem file_get_contents () : $content = @file_get_contents($site);


86
Pamiętaj, aby stosować ścisłe porównanie: jeśli ($ content === FALSE) .Jeśli plik zawiera „0”, spowoduje to wygenerowanie fałszywego negatywu.
Aram Kocharyan

7
Cześć, to nie zadziałało dla mnie, dodanie @ nadal powoduje przechwycenie E_WARNING przez jakiś globalny (nie mój) moduł obsługi błędów, a mój skrypt umiera, zanim mam szansę obsłużyć zwracaną wartość. Jakieś pomysły? tnx.
Sagi Mann

1
Wykryto efekt uboczny: jeśli plik nie istnieje, skrypt zatrzymuje się na linii @ file_get_contents.
Dax,

To nie działa dla mnie, nawet jeśli będzie to właściwe rozwiązanie. Mam ostrzeżenie o przekroczeniu limitu czasu bez otrzymania danych, ale $ content === FALSE nie jest „wyzwalane” ($ site jest wywoływany z serwera localhost, zauważ, że mam dane szybko, jeśli wkleję sobie adres URL do przeglądarki).
Oliver

4
Chociaż odpowiedź jest bardzo stara, nadal sugeruję dodanie do odpowiedzi uwagi, że użycie @może negatywnie wpłynąć na wydajność. Zobacz tę odpowiedź na powiązany post, który wyjaśnia dość dobrze.
Fr0zenFyr

148

Możesz również ustawić swój moduł obsługi błędów jako anonimową funkcję, która wywołuje wyjątek i użyć try / catch dla tego wyjątku.

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

Wygląda na to, że dużo kodu łapie jeden mały błąd, ale jeśli używasz wyjątków w całej aplikacji, musisz to zrobić tylko raz, na górze (na przykład w dołączonym pliku konfiguracyjnym), i to zrobi przekonwertować wszystkie swoje błędy na wyjątki.


To jedno z największych ulepszeń PHP, jakie do tej pory widziałem. Dziękuję enobrev
Tomasz Smykowski

@enobrev, Dlaczego podajesz tę samą wartość zarówno dla numeru błędu, jak i ważności?
Pacerier

Nie ma konkretnego powodu poza sposobem oferowania czegoś użytecznego w $ wyjątek-> getCode (), ponieważ set_error_handler nie oferuje zmiennej numeru błędu (niestety).
enobrev

1
@enobrev Nie zapomnij przywrócić obsługi błędów w funkcji anonimowej przed zgłoszeniem wyjątku. Można obsłużyć wyjątek, w takim przypadku moduł obsługi jest nadal ustawiony na zgłoszenie tego wyjątku, który może okazać się nieoczekiwany i wprowadzić dziwne, trudne do debugowania zachowanie, gdy wystąpi inny błąd w obsłudze wyjątków.
Josef Sábl


67

Mój ulubiony sposób na zrobienie tego jest dość prosty:

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

Znalazłem to po eksperymentach z try/catchpowyższym @enobrev, ale pozwala to na użycie mniej długiego (i IMO, bardziej czytelnego) kodu. Po prostu używamy, error_get_lastaby uzyskać tekst ostatniego błędu i file_get_contentszwraca błąd w przypadku niepowodzenia, więc proste „jeśli” może to złapać.


2
To najłatwiejsze i najlepsze rozwiązanie tego problemu! Może to zrobić, @file_get_contentsaby ukryć zgłaszanie błędów do przeglądarki.
EDP

1
Przyznaję, że spośród wszystkich odpowiedzi jest to jedyna sensowna opcja - gdybyśmy ją rozszerzyli, @file_get_contentsaby wyłączyć ostrzeżenie i przetestować wartość wyniku za pomocą === FALSE.
kostix

11
Spowoduje to błędy dla udanych żądań, które nie zwracają treści lub zwracają wartość, która ma wartość false. Powinno byćif (false !== ($data = file_get_contents ()))
GordonM,

Dokumentacja nie wyjaśnia tego, ale użycie @ może spowodować, error_get_lastże nic nie zwróci z mojego doświadczenia
Glenn Schmidt

33

Możesz dodać @: $content = @file_get_contents($site);

Pominie to ostrzeżenie - używaj oszczędnie! . Zobacz Operatory kontroli błędów

Edycja: po usunięciu „http: //” nie szukasz już strony internetowej, ale plik na dysku o nazwie „www.google .....”


To jedyna rzecz, która naprawdę działa - nie mogłem w żaden sposób ukryć komunikatu „nie udało się otworzyć strumienia”.
Olaf

21

Jedną z możliwości jest wyeliminowanie błędu, a także zgłoszenie wyjątku, który można złapać później. Jest to szczególnie przydatne, jeśli w kodzie znajduje się wiele wywołań funkcji file_get_contents (), ponieważ nie trzeba tłumić i obsługiwać ich wszystkich ręcznie. Zamiast tego można wykonać kilka wywołań tej funkcji w jednym bloku 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

Oto jak to zrobiłem ... Nie trzeba blokować try-catch ... Najlepsze rozwiązanie jest zawsze najprostsze ... Ciesz się!

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

4
-1: działa to, jeśli pojawi się błąd 404 lub coś, ale nie, jeśli w ogóle nie uda się połączyć z serwerem (np. Zła nazwa domeny). Myślę, że $http_response_headerw takim przypadku nie jest aktualizowany, ponieważ nie otrzymano odpowiedzi HTTP.
Nathan Reed

1
Jak powiedział @NathanReed, należy sprawdzić $ treść nie jest fałszem (z ===) jako, że to, co dostaje zwrot, jeżeli wniosek nie trafia do żadnego w ogóle
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
}

To nie działa Jeśli $urlnie znaleziono 404, ostrzeżenie będzie nadal wyświetlane.
Raptor

Raptor, poprawiłem odpowiedź za pomocą stream_context_create (); Nic lepszego ... "@" nie jest zalecane
RafaSashi

1
ignore_errorsinstruuje tylko kontekst HTTP, aby nie interpretował kodów statusu odpowiedzi HTTP > = 400 jako błędów. Choć marginalnie spokrewniony, nie odpowiada na pytanie o obsługę błędów PHP.
niedz.

Dzięki za ignore_errorsopcję! Właśnie tego potrzebowałem!
Modder

6

Oto jak sobie z tym poradzić:

$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

Najlepiej byłoby ustawić własne procedury obsługi błędów i wyjątków, które zrobią coś pożytecznego, np. Zalogowanie do pliku lub przesłanie krytycznych wiadomości e-mail. http://www.php.net/set_error_handler


1

Możesz użyć tego skryptu

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

Wymaga to ścisłego porównania: if ($url === true)...ponieważ jeśli otrzymujesz odpowiedź 0lub jest pusty, powoduje to błąd połączenia.
Daniel W.

1

Ponieważ PHP 4 używa 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

Najprostszym sposobem na to jest po prostu wstawienie @ przed file_get_contents, tj. mi.:

$content = @file_get_contents($site); 

1

coś takiego:

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

Przed użyciem file_get_contents () należy użyć funkcji file_exists (). W ten sposób unikniesz ostrzeżenia php.

$file = "path/to/file";

if(file_exists($file)){
  $content = file_get_contents($file);
}


-3

Zmień plik php.ini

allow_url_fopen = On

allow_url_include = On

Nie rób tego Szczególnie nie zezwalaj na dołączanie adresów URL. Nie wierz mi. Został on domyślnie wyłączony z bardzo dobrego powodu # c99.
Daniel W.

-3

Spróbuje to uzyskać dane, jeśli to nie zadziała, złapie błąd i pozwoli ci zrobić wszystko, czego potrzebujesz w ramach tego połowu.

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 nie zawsze rzuca wyjątek
marlar

Czy chcesz edytować swoją odpowiedź i powiedzieć nam, o której godzinie file_get_content zgłasza wyjątki?
Ravinder Payal

1
Chociaż ten kod może odpowiedzieć na pytanie, zapewnienie dodatkowego kontekstu dotyczącego tego, dlaczego i / lub jak ten kod odpowiada na pytanie, poprawia jego długoterminową wartość.
Jay Blanchard

-3

Powinieneś także ustawić

allow_url_use = On 

W twojej php.iniprzestać otrzymywać ostrzeżenia.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.