Come posso gestire l'avviso della funzione file_get_contents () in PHP?


312

Ho scritto un codice PHP come questo

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

Ma quando rimuovo "http: //" da $site ottengo il seguente avviso:

Avviso: file_get_contents (www.google.com) [function.file-get-contents]: impossibile aprire lo stream:

Ci ho provato trye catchnon ha funzionato.


2
Anche un approccio interessante: stackoverflow.com/questions/6718598/…
Hugo Stieglitz


Usare try-catch con set_error_handler funzione come ha detto qui stackoverflow.com/a/3406181/1046909
MingalevME

2
Se rimuovi http: // dall'URL, stai cercando un file "www.google.com" sul tuo disco locale.
Rauli Rajande,

Come può ottenere così tanta attenzione e voti positivi. Perché dovresti rimuovere le informazioni sul protocollo. Anche nel 2008 avevi FTP e HTTPS.
Daniel W.

Risposte:


507

Passaggio 1: controlla il codice di ritorno: if($content === FALSE) { // handle error here... }

Passaggio 2: sopprimere l'avviso inserendo un operatore di controllo degli errori (ovvero @) davanti alla chiamata a file_get_contents () : $content = @file_get_contents($site);


86
Ricorda di utilizzare un confronto rigoroso: if ($ content === FALSE). Se il file contiene "0", verrà attivato un falso negativo.
Aram Kocharyan,

7
Ciao, questo non ha funzionato per me, l'aggiunta di @ fa sì che E_WARNING venga catturato da un gestore di errori globale (non mio) e il mio script muore prima che io abbia la possibilità di gestire il valore restituito. Qualche idea? tnx.
Sagi Mann,

1
Effetto collaterale rilevato: se il file non esiste, lo script si interrompe sulla riga @file_get_contents.
Dax,

Questo non funziona per me, anche se sta per essere la soluzione giusta. Ho un avviso di timeout senza dati ricevuti, ma $ content === FALSE non viene "attivato" ($ site viene chiamato da un server localhost, nota che ho dei dati rapidamente se incollo l'URL in un browser).
Oliver,

4
Sebbene la risposta sia molto vecchia, suggerisco comunque di aggiungere una nota alla tua risposta che l'utilizzo @potrebbe influire negativamente sulle prestazioni. Vedi questa risposta su un post correlato che spiega abbastanza bene.
Fr0zenFyr,

148

È anche possibile impostare il gestore degli errori come funzione anonima che chiama un eccezione e utilizzare un try / catch su tale eccezione.

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

Sembra un sacco di codice per rilevare un piccolo errore, ma se stai usando eccezioni in tutta la tua app, dovresti farlo solo una volta, in alto (in un file di configurazione incluso, per esempio), e lo farà converti tutti gli errori in Eccezioni in tutto.


È uno dei maggiori miglioramenti di PHP che ho visto finora. Grazie enobrev
Tomasz Smykowski il

@enobrev, Perché metti lo stesso valore sia per il numero di errore che per la gravità?
Pacerier,

Nessun motivo specifico oltre a un mezzo per offrire qualcosa di utile in $ exception-> getCode (), poiché set_error_handler non offre una variabile numerica di errore (purtroppo).
enobrev,

1
@enobrev Non dimenticare di ripristinare il gestore errori all'interno della funzione anonima prima di generare un'eccezione. L'eccezione può essere gestita e in tal caso il gestore è ancora impostato per generare questa particolare eccezione che può apparire inaspettata e introdurre comportamenti strani, difficili da eseguire il debug, quando si verifica un altro errore nella gestione delle eccezioni.
Josef Sábl,

1
Consiglierei di includere la chiamata
restore_error_handler

67

Il mio modo preferito per farlo è abbastanza semplice:

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

Ho trovato questo dopo aver sperimentato da try/catchfrom @enobrev sopra, ma questo consente un codice meno lungo (e IMO, più leggibile). Usiamo semplicemente error_get_lastper ottenere il testo dell'ultimo errore e file_get_contentsrestituisce false in caso di errore, quindi un semplice "if" può capirlo.


2
Questa è la soluzione più semplice e migliore per questo problema! Magari @file_get_contentsriesci a sopprimere l'errore che riporta al browser.
EDP ​​il

1
Devo ammettere che tra tutte le risposte questa è l'unica ragionevole - se la aumentassimo per usarla @file_get_contentsper sopprimere l'avvertimento e testare il valore del risultato usando === FALSE.
kostix,

11
Ciò attiverà errori per richieste riuscite che non restituiscono un corpo o restituiscono uno che restituisce false. Dovrebbe essereif (false !== ($data = file_get_contents ()))
GordonM,

La documentazione non chiarisce, ma l'uso di @ può error_get_lastnon restituire nulla nella mia esperienza
Glenn Schmidt,

33

Puoi anteporre un @: $content = @file_get_contents($site);

Questo sopprimerà qualsiasi avvertimento - usare con parsimonia! . Vedere Operatori di controllo errori

Modifica: quando rimuovi "http: //" non stai più cercando una pagina web, ma un file sul tuo disco chiamato "www.google ....."


Questa è l'unica cosa che funziona davvero: non ho potuto sopprimere il messaggio "Impossibile aprire lo stream" in nessun altro modo.
Olaf,

21

Un'alternativa è eliminare l'errore e generare anche un'eccezione che è possibile rilevare in seguito. Ciò è particolarmente utile se nel tuo codice sono presenti più chiamate a file_get_contents (), poiché non è necessario eliminarle e gestirle tutte manualmente. Al contrario, è possibile effettuare più chiamate a questa funzione in un singolo blocco 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

Ecco come l'ho fatto ... Non c'è bisogno del blocco try-catch ... La migliore soluzione è sempre la più semplice ... Divertiti!

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

4
-1: funziona se ricevi un errore 404 o qualcosa del genere, ma non se non riesci a connetterti al server (es. Nome di dominio errato). Penso che $http_response_headernon sia aggiornato in quel caso, poiché non viene ricevuta alcuna risposta HTTP.
Nathan Reed,

1
Come ha detto @NathanReed, dovresti verificare che $ content non sia falso (con ===) poiché questo è ciò che viene restituito se la richiesta non riesce a connettersi affatto
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
}

Questo non funziona Se $urlnon si trova 404, verrà comunque visualizzato un avviso.
Raptor

Giusto Raptor, ho migliorato la risposta con stream_context_create (); Niente di meglio ... "@" non raccomandato
RafaSashi

1
ignore_errorsindica solo al contesto HTTP di non interpretare i codici di stato della risposta HTTP > = 400 come errori. Sebbene marginalmente correlato, ciò non risponde alla domanda sulla gestione degli errori PHP.
dom

Grazie per l' ignore_errorsopzione! Questo è quello di cui avevo bisogno!
Modder

6

Ecco come lo gestisco:

$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

La cosa migliore sarebbe impostare i propri gestori di errori ed eccezioni che faranno qualcosa di utile come registrarlo in un file o inviare via e-mail quelli critici. http://www.php.net/set_error_handler


1

Potresti usare questo 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";
}

Ciò richiede un confronto rigoroso: if ($url === true)...perché se si ottiene come risposta 0o vuoto, si genera un errore di connessione.
Daniel W.

1

Dato che PHP 4 usa 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

Il modo più semplice per farlo è semplicemente anteporre un @ prima di file_get_contents, i. e .:

$content = @file_get_contents($site); 

1

qualcosa come questo:

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

È necessario utilizzare la funzione file_exists () prima di utilizzare file_get_contents (). In questo modo eviterai l'avvertimento php.

$file = "path/to/file";

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


-3

Cambia il file php.ini

allow_url_fopen = On

allow_url_include = On

Non farlo Soprattutto non consentire le URL incluse. Non credermi. È stato disabilitato di default per un'ottima ragione # c99.
Daniel W.

-3

Questo tenterà di ottenere i dati, se non funziona, rileverà l'errore e ti consentirà di fare tutto ciò che ti serve all'interno della cattura.

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 non sempre genera un'eccezione
marlar

Vorresti modificare la tua risposta e dirci che a che ora il file_get_content genera eccezioni?
Ravinder Payal,

1
Mentre questo codice può rispondere alla domanda, fornendo un contesto aggiuntivo riguardo al perché e / o al modo in cui questo codice risponde alla domanda migliora il suo valore a lungo termine.
Jay Blanchard,

-3

Dovresti anche impostare il

allow_url_use = On 

nella vostra php.iniper non ricevere avvisi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.