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é.


2
Également une approche intéressante: stackoverflow.com/questions/6718598/…
Hugo Stieglitz


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


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.


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.


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 ....."


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

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

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
}

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

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


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

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

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

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

1
if (!file_get_contents($data)) {
  exit('<h1>ERROR MESSAGE</h1>');
} else {
      return file_get_contents($data);
}

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

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

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

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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.