230 votes

Comment puis-je vérifier si une URL existe via PHP ?

Comment vérifier si une URL existe (et non 404) en PHP ?

5 votes

348voto

karim79 Points 178055

Ici :

$file = 'http://www.example.com/somefile.jpg';
$file_headers = @get_headers($file);
if(!$file_headers || $file_headers[0] == 'HTTP/1.1 404 Not Found') {
    $exists = false;
}
else {
    $exists = true;
}

De aquí y juste en dessous le post ci-dessus, il y a un bouclette solution :

function url_exists($url) {
    return curl_init($url) !== false;
}

20 votes

J'ai peur que la méthode CURL ne fonctionne pas de cette façon. Regarde ça : stackoverflow.com/questions/981954/

0 votes

Devrions-nous fermer le filehande ?

8 votes

Certains sites web ont une $file_headers[0] sur la page d'erreur. par exemple, youtube.com. sa page d'erreur ayant cette valeur comme HTTP/1.0 404 Not Found (la différence est 1.0 et 1.1). Que faire alors ?

62voto

MoonLite Points 367

Lorsqu'on cherche à savoir si une url existe à partir de php, il faut faire attention à quelques éléments :

  • L'url elle-même est-elle valide (une chaîne, non vide, bonne syntaxe), ce qui est rapide à vérifier côté serveur.
  • L'attente d'une réponse peut prendre du temps et bloquer l'exécution du code.
  • Les en-têtes retournés par get_headers() ne sont pas tous bien formés.
  • Utilisez le curl (si vous le pouvez).
  • Empêchez la récupération de l'ensemble du corps/contenu, mais demandez uniquement les en-têtes.
  • Pensez à rediriger les urls :
  • Voulez-vous que le premier code soit renvoyé ?
  • Ou suivre toutes les redirections et renvoyer le dernier code ?
  • Vous pourriez vous retrouver avec un 200, mais il pourrait être redirigé en utilisant des balises méta ou du javascript. Il est difficile de savoir ce qui se passe ensuite.

N'oubliez pas que, quelle que soit la méthode utilisée, l'attente d'une réponse prend du temps.
Tout le code peut (et va probablement) s'arrêter jusqu'à ce que vous connaissiez le résultat ou que les requêtes aient expiré.

Par exemple : le code ci-dessous pourrait prendre un LONG moment pour afficher la page si les urls sont invalides ou inaccessibles :

<?php
$urls = getUrls(); // some function getting say 10 or more external links

foreach($urls as $k=>$url){
  // this could potentially take 0-30 seconds each
  // (more or less depending on connection, target site, timeout settings...)
  if( ! isValidUrl($url) ){
    unset($urls[$k]);
  }
}

echo "yay all done! now show my site";
foreach($urls as $url){
  echo "<a href=\"{$url}\">{$url}</a><br/>";
}

Les fonctions ci-dessous pourraient vous être utiles, vous voudrez probablement les modifier pour les adapter à vos besoins :

    function isValidUrl($url){
        // first do some quick sanity checks:
        if(!$url || !is_string($url)){
            return false;
        }
        // quick check url is roughly a valid http request: ( http://blah/... ) 
        if( ! preg_match('/^http(s)?:\/\/[a-z0-9-]+(\.[a-z0-9-]+)*(:[0-9]+)?(\/.*)?$/i', $url) ){
            return false;
        }
        // the next bit could be slow:
        if(getHttpResponseCode_using_curl($url) != 200){
//      if(getHttpResponseCode_using_getheaders($url) != 200){  // use this one if you cant use curl
            return false;
        }
        // all good!
        return true;
    }

    function getHttpResponseCode_using_curl($url, $followredirects = true){
        // returns int responsecode, or false (if url does not exist or connection timeout occurs)
        // NOTE: could potentially take up to 0-30 seconds , blocking further code execution (more or less depending on connection, target site, and local timeout settings))
        // if $followredirects == false: return the FIRST known httpcode (ignore redirects)
        // if $followredirects == true : return the LAST  known httpcode (when redirected)
        if(! $url || ! is_string($url)){
            return false;
        }
        $ch = @curl_init($url);
        if($ch === false){
            return false;
        }
        @curl_setopt($ch, CURLOPT_HEADER         ,true);    // we want headers
        @curl_setopt($ch, CURLOPT_NOBODY         ,true);    // dont need body
        @curl_setopt($ch, CURLOPT_RETURNTRANSFER ,true);    // catch output (do NOT print!)
        if($followredirects){
            @curl_setopt($ch, CURLOPT_FOLLOWLOCATION ,true);
            @curl_setopt($ch, CURLOPT_MAXREDIRS      ,10);  // fairly random number, but could prevent unwanted endless redirects with followlocation=true
        }else{
            @curl_setopt($ch, CURLOPT_FOLLOWLOCATION ,false);
        }
//      @curl_setopt($ch, CURLOPT_CONNECTTIMEOUT ,5);   // fairly random number (seconds)... but could prevent waiting forever to get a result
//      @curl_setopt($ch, CURLOPT_TIMEOUT        ,6);   // fairly random number (seconds)... but could prevent waiting forever to get a result
//      @curl_setopt($ch, CURLOPT_USERAGENT      ,"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1");   // pretend we're a regular browser
        @curl_exec($ch);
        if(@curl_errno($ch)){   // should be 0
            @curl_close($ch);
            return false;
        }
        $code = @curl_getinfo($ch, CURLINFO_HTTP_CODE); // note: php.net documentation shows this returns a string, but really it returns an int
        @curl_close($ch);
        return $code;
    }

    function getHttpResponseCode_using_getheaders($url, $followredirects = true){
        // returns string responsecode, or false if no responsecode found in headers (or url does not exist)
        // NOTE: could potentially take up to 0-30 seconds , blocking further code execution (more or less depending on connection, target site, and local timeout settings))
        // if $followredirects == false: return the FIRST known httpcode (ignore redirects)
        // if $followredirects == true : return the LAST  known httpcode (when redirected)
        if(! $url || ! is_string($url)){
            return false;
        }
        $headers = @get_headers($url);
        if($headers && is_array($headers)){
            if($followredirects){
                // we want the last errorcode, reverse array so we start at the end:
                $headers = array_reverse($headers);
            }
            foreach($headers as $hline){
                // search for things like "HTTP/1.1 200 OK" , "HTTP/1.0 200 OK" , "HTTP/1.1 301 PERMANENTLY MOVED" , "HTTP/1.1 400 Not Found" , etc.
                // note that the exact syntax/version/output differs, so there is some string magic involved here
                if(preg_match('/^HTTP\/\S+\s+([1-9][0-9][0-9])\s+.*/', $hline, $matches) ){// "HTTP/*** ### ***"
                    $code = $matches[1];
                    return $code;
                }
            }
            // no HTTP/xxx found in headers:
            return false;
        }
        // no headers :
        return false;
    }

0 votes

Pour une raison quelconque, getHttpResponseCode_using_curl() renvoie toujours 200 dans mon cas.

2 votes

Si quelqu'un a le même problème, vérifiez les serveurs de noms dns utilisez opendns sans followredirects stackoverflow.com/a/11072947/1829460

0 votes

+1 pour être la seule réponse à traiter les redirections. J'ai changé le return $code a if($code == 200){return true;} return false; pour ne trier que les réussites

50voto

lunarnet76 Points 197
$headers = @get_headers($this->_value);
if(strpos($headers[0],'200')===false)return false;

donc chaque fois que vous contactez un site web et que vous obtenez autre chose que 200 ok, cela fonctionnera.

14 votes

Mais si c'est une redirection ? Le domaine est toujours valide, mais il ne sera pas pris en compte.

4 votes

Ci-dessus sur une ligne : return strpos(@get_headers($url)[0],'200') === false ? false : true . Cela pourrait être utile.

0 votes

En PHP, $this est une référence à l'objet courant. Référence : php.net/manual/fr/language.oop5.basic.php L'amorce : phpro.org/tutoriels/Programmation orientée objet-avec-PHP.html Il est fort probable que l'extrait de code provienne d'un cours et n'ait pas été corrigé en conséquence.

21voto

mebjas Points 154

Vous ne pouvez pas utiliser curl sur certains serveurs vous pouvez utiliser ce code

<?php
$url = 'http://www.example.com';
$array = get_headers($url);
$string = $array[0];
if(strpos($string,"200"))
  {
    echo 'url exists';
  }
  else
  {
    echo 'url does not exist';
  }
?>

1 votes

Cela peut ne pas fonctionner pour les redirections 302-303 ou par exemple 304 Not Modified

8voto

Randy Skretka Points 682
$url = 'http://google.com';
$not_url = 'stp://google.com';

if (@file_get_contents($url)): echo "Found '$url'!";
else: echo "Can't find '$url'.";
endif;
if (@file_get_contents($not_url)): echo "Found '$not_url!";
else: echo "Can't find '$not_url'.";
endif;

// Found 'http://google.com'!Can't find 'stp://google.com'.

2 votes

Cela ne fonctionnera pas si l'option allow-url-fopen est désactivée. - php.net/manual/en/

2 votes

Je suggère de lire uniquement le premier octet... if (@file_get_contents($url,false,NULL,0,1))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X