Comment puis-je gérer l'avertissement de la fonction file_get_contents () en PHP?

312

J'ai écrit un code PHP comme celui-ci

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

Mais lorsque je supprime "http: //" de $sitej'obtiens l'avertissement suivant:

Avertissement: file_get_contents (www.google.com) [function.file-get-contents]: impossible d'ouvrir le flux:

J'ai essayé tryet catchça n'a pas marché.

Waseem
la source
2
Également une approche intéressante: stackoverflow.com/questions/6718598/…
Hugo Stieglitz
Connexe: stackoverflow.com/q/2002610
Fr0zenFyr
Utilisez try-catch avec set_error_handler-function comme indiqué ici stackoverflow.com/a/3406181/1046909
MingalevME
2
Si vous supprimez http: // de l'URL, vous recherchez un fichier "www.google.com" sur votre disque local.
Rauli Rajande
Comment cela peut-il attirer autant d'attention et de votes positifs? Pourquoi voudriez-vous supprimer les informations de protocole. Même en 2008, vous disposiez de FTP et HTTPS.
Daniel W.

Réponses:

507

Étape 1: vérifiez le code retour: if($content === FALSE) { // handle error here... }

Étape 2: supprimez l'avertissement en plaçant un opérateur de contrôle d'erreur (c'est-à-dire @) devant l'appel à file_get_contents () : $content = @file_get_contents($site);

Roel
la source
86
N'oubliez pas d'utiliser une comparaison stricte: si ($ content === FALSE) .Si le fichier contient "0", alors il déclenchera un faux négatif.
Aram Kocharyan
7
Salut, cela n'a pas fonctionné pour moi, l'ajout de @ fait que E_WARNING est intercepté par un gestionnaire d'erreur global (pas le mien), et mon script meurt avant que j'aie la chance de gérer la valeur de retour. Des idées? tnx.
Sagi Mann
1
Effet secondaire détecté: si le fichier n'existe pas, le script s'arrête à la ligne @file_get_contents.
Dax
Cela ne fonctionne pas pour moi, même si c'est sur le point d'être la bonne solution. J'ai un avertissement de délai d'attente sans données reçues, mais $ content === FALSE n'est pas "déclenché" ($ site étant appelé depuis un serveur localhost, notez que j'ai des données rapidement si je me colle l'URL dans un navigateur).
Oliver
4
Bien que la réponse soit très ancienne, je suggère toujours d'ajouter une note à votre réponse selon laquelle l'utilisation @peut avoir un impact négatif sur les performances. Voir cette réponse sur un poste connexe qui explique assez bien.
Fr0zenFyr
148

Vous pouvez également définir votre gestionnaire d'erreurs comme une fonction anonyme qui appelle une exception et utiliser un try / catch sur cette exception.

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

Il semble que beaucoup de code détecte une petite erreur, mais si vous utilisez des exceptions dans votre application, vous n'aurez besoin de le faire qu'une seule fois, tout en haut (dans un fichier de configuration inclus, par exemple), et il le fera convertir toutes vos erreurs en exceptions tout au long.

enobrev
la source
C'est l'une des meilleures améliorations PHP que j'ai vues jusqu'à présent. Merci enobrev
Tomasz Smykowski
@enobrev, Pourquoi mettez-vous la même valeur pour le numéro d'erreur et la gravité?
Pacerier
Aucune raison spécifique à part un moyen d'offrir quelque chose d'utile dans $ exception-> getCode (), puisque set_error_handler n'offre pas de variable de numéro d'erreur (malheureusement).
enobrev
1
@enobrev N'oubliez pas de restaurer le gestionnaire d'erreurs dans la fonction anonyme avant de lever l'exception. Une exception peut être gérée et dans ce cas, le gestionnaire est toujours configuré pour lever cette exception particulière qui peut apparaître comme inattendue et introduire un comportement étrange et difficile à déboguer lorsqu'il y a une autre erreur dans la gestion des exceptions.
Josef Sábl
1
Je recommanderais d'inclure l'appel de restore_error_handler () dans le bloc enfin
peschanko
67

Ma façon préférée de le faire est assez simple:

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

J'ai trouvé cela après avoir expérimenté avec le try/catch@enobrev ci-dessus, mais cela permet un code moins long (et IMO, plus lisible). Nous utilisons simplement error_get_lastpour obtenir le texte de la dernière erreur, et file_get_contentsrenvoie false en cas d'échec, donc un simple "si" peut le détecter.

Laurie
la source
2
C'est la solution la plus simple et la meilleure pour ce problème! Peut-être le faire @file_get_contentspour supprimer le rapport d'erreur au navigateur.
EDP
1
J'admets que parmi toutes les réponses, c'est la seule raisonnable - si nous l'augmentions pour l'utiliser @file_get_contentspour supprimer l'avertissement et tester la valeur du résultat à l'aide === FALSE.
kostix
11
Cela déclenchera des erreurs pour les demandes réussies qui ne renvoient pas de corps, ou en renverra une qui est évaluée à false. Devrait êtreif (false !== ($data = file_get_contents ()))
GordonM
La documentation n'est pas claire, mais l'utilisation de @ peut error_get_lastne rien retourner de mon expérience
Glenn Schmidt
33

Vous pouvez ajouter un @: $content = @file_get_contents($site);

Cela supprimera tout avertissement - utilisez-le avec parcimonie! . Voir Opérateurs de contrôle d'erreur

Edit: Lorsque vous supprimez le 'http: //', vous ne recherchez plus une page Web, mais un fichier sur votre disque appelé "www.google ....."

Greg
la source
C'est la seule chose qui fonctionne vraiment - je ne pouvais pas supprimer le message "Impossible d'ouvrir le flux" de toute autre manière.
Olaf
21

Une alternative consiste à supprimer l'erreur et à lever également une exception que vous pourrez intercepter ultérieurement. Cela est particulièrement utile s'il existe plusieurs appels à file_get_contents () dans votre code, car vous n'avez pas besoin de les supprimer et de les gérer tous manuellement. Au lieu de cela, plusieurs appels peuvent être effectués vers cette fonction dans un seul bloc 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();
}
Aram Kocharyan
la source
15

Voici comment je l'ai fait ... Pas besoin de bloc try-catch ... La meilleure solution est toujours la plus simple ... Profitez-en!

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

la source
4
-1: cela fonctionne si vous obtenez une erreur 404 ou quelque chose, mais pas si vous ne vous connectez pas du tout au serveur (par exemple un nom de domaine incorrect). Je pense que $http_response_headern'est pas mis à jour dans ce cas, car aucune réponse HTTP n'est reçue.
Nathan Reed
1
Comme l'a dit @NathanReed, vous devriez vérifier que $ content n'est pas faux (avec ===) car c'est ce qui est renvoyé si la demande ne se connecte pas du tout
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
la source
Ça ne marche pas. Si le $url404 est introuvable, un avertissement apparaîtra toujours.
Raptor
Raptor droit, j'ai amélioré la réponse avec stream_context_create (); Rien de mieux ... "@" déconseillé
RafaSashi
1
ignore_errorsindique uniquement au contexte HTTP de ne pas interpréter les codes d'état de réponse HTTP > = 400 comme des erreurs. Bien que marginalement lié, cela ne répond pas à la question de la gestion des erreurs PHP.
dim
Merci pour l' ignore_errorsoption! Voilà ce dont j'avais besoin!
Modder
6

Voici comment je gère cela:

$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
la source
4

La meilleure chose serait de définir vos propres gestionnaires d'erreurs et d'exceptions qui feront quelque chose d'utile comme la journalisation dans un fichier ou l'envoi par e-mail des fichiers critiques. http://www.php.net/set_error_handler


la source
1

Vous pouvez utiliser ce 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";
}
ogie
la source
Cela nécessite une comparaison stricte: if ($url === true)...car si vous obtenez une réponse 0ou vide, cela soulève une erreur de connexion.
Daniel W.
1

Depuis PHP 4, utilisez 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;
}
Bob Stein
la source
1

La façon la plus simple de le faire est de simplement ajouter un @ avant file_get_contents, i. e .:

$content = @file_get_contents($site); 
Muhammad Adeel Malik
la source
1

quelque chose comme ça:

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]);
}
Michael de Oz
la source
1
if (!file_get_contents($data)) {
  exit('<h1>ERROR MESSAGE</h1>');
} else {
      return file_get_contents($data);
}
Frank Rich
la source
-2

Vous devez utiliser la fonction file_exists () avant d'utiliser file_get_contents (). De cette façon, vous éviterez l'avertissement php.

$file = "path/to/file";

if(file_exists($file)){
  $content = file_get_contents($file);
}
Jesús Díaz
la source
Cela ne fonctionnerait que si vous appelez un fichier local et que vous avez les bonnes autorisations pour vérifier le fichier local s'il existe
rubo77
-3

Changer le fichier php.ini

allow_url_fopen = On

allow_url_include = On
Antério Vieira
la source
Ne fais pas ça. Surtout n'autorisez pas les URL. Ne me crois pas. Il a été désactivé par défaut pour une très bonne raison # c99.
Daniel W.
-3

Cela essaiera d'obtenir les données, si cela ne fonctionne pas, il détectera l'erreur et vous permettra de faire tout ce dont vous avez besoin dans la capture.

try {
    $content = file_get_contents($site);
} catch(\Exception $e) {
    return 'The file was not found';
}
Brad
la source
-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);
});
kta
la source
file_get_content ne lève pas toujours une exception
marlar
Souhaitez-vous modifier votre réponse et nous dire à quel moment le fichier_get_content lève des exceptions?
Ravinder Payal
1
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire concernant pourquoi et / ou comment ce code répond à la question améliore sa valeur à long terme.
Jay Blanchard
-3

Vous devez également définir

allow_url_use = On 

dans votre php.inipour cesser de recevoir des avertissements.

GHAV
la source