Bir URL'nin geçerli olup olmadığını kontrol etmenin en iyi yolu


152

$myoutputDeğişkende depolanan dizenin geçerli bir bağlantı sözdizimi içerip içermediğini veya yalnızca normal bir metin olup olmadığını kontrol etmek için PHP'yi kullanmak istiyorum . Aradığım işlev veya çözüm, GET parametreli olanlar dahil tüm bağlantı biçimlerini tanımalıdır.

Birçok sitede önerilen, dizeyi gerçekten sorgulamak için (CURL veya file_get_contents()işlev kullanarak ) bir çözüm benim durumumda mümkün değildir ve bundan kaçınmak isterim.

Normal ifadeleri veya başka bir çözümü düşündüm.


CURL kullanmak veya HTTP içeriğini almak yavaş olabilir, daha hızlı ve neredeyse aynı derecede güvenilir bir şey istiyorsanız, ana bilgisayar adında gethostbyaddr () kullanmayı düşünün. Bir IP'ye çözümlenirse, muhtemelen bir web sitesine sahiptir. Tabii ki bu ihtiyaçlarınıza bağlıdır.
TravisO

Yanıtlar:


311

Yerel bir Filtre Doğrulayıcı kullanabilirsiniz

filter_var($url, FILTER_VALIDATE_URL);

Değeri URL olarak doğrular (» http://www.faqs.org/rfcs/rfc2396'ya göre ), isteğe bağlı olarak gerekli bileşenlerle. Geçerli bir URL'nin http: // HTTP protokolünü belirtmeyebileceğine dikkat edin, bu nedenle URL'nin beklenen bir protokol, örneğin ssh: // veya mailto: kullandığını belirlemek için daha fazla doğrulama gerekebilir. İşlevin yalnızca geçerli olan ASCII URL'leri bulacağını unutmayın; uluslararasılaştırılmış alan adları (ASCII olmayan karakterler içeren) başarısız olur.

Misal:

if (filter_var($url, FILTER_VALIDATE_URL) === FALSE) {
    die('Not a valid URL');
}

9
@Raveren, bunlar geçerli URL'ler olduğundan beklenen davranış.
Gordon

8
Unutmayın FILTER_VALIDATE_URLbir url'nin protokolü doğrulama yapmaz. Yani ssh://, ftp://vb geçecek.
Seph

4
@SephVelut, bunlar geçerli URL'ler olduğundan beklenen davranış.
Gordon

1
o verir ttp gibi URL'ler: //amazon.com
Elia Weiss

4
@JoshHabdas, sanırım noktayı kaçırıyorsun. PHP kodu, iddia ettiği şeyi tam olarak yapar. Ama zihninizi okuyamaz. Geçersiz ve istenmeyen arasında büyük bir fark var .. İstenmeyen çok özneldir, bu yüzden bu ayrıntıyı hesaplamak programcıya bırakılmıştır. Ayrıca kodun URL'yi doğruladığını ancak var olduğunu kanıtlamadığını da not edebilirsiniz. Bir kullanıcının "amazon", "amozon" u yanlış yazması PHP'nin hatası değildir, bu doğrulayacak, ancak yine de istenmeyen bir durumdur.
JBH

24

İşte orada bulduğum en iyi öğretici:

http://www.w3schools.com/php/filter_validate_url.asp

<?php
$url = "http://www.qbaki.com";

// Remove all illegal characters from a url
$url = filter_var($url, FILTER_SANITIZE_URL);

// Validate url
if (filter_var($url, FILTER_VALIDATE_URL) !== false) {
echo("$url is a valid URL");
} else {
echo("$url is not a valid URL");
}
?>

Olası işaretler:

FILTER_FLAG_SCHEME_REQUIRED - URL must be RFC compliant (like http://example)
FILTER_FLAG_HOST_REQUIRED - URL must include host name (like http://www.example.com)
FILTER_FLAG_PATH_REQUIRED - URL must have a path after the domain name (like www.example.com/example1/)
FILTER_FLAG_QUERY_REQUIRED - URL must have a query string (like "example.php?name=Peter&age=37")

2
Sadece bir nit: !filter_var(...) === false==> filter_var(...) === trueveya sadece filter_var(...). :)
Domenico De Felice

@ ErichGarcía bu kod, OP'nin istediği gibi geçerli bir HTTP / S URL'si olup olmadığını kontrol etmez. Bu, ssh: //, ftp: // vb. Gibi şeyleri
iletir

FILTER_VALIDATE_URL kullanmayın. Dağınık ve güvenilmez. Örneğin, geçerli ttps://www.youtube.comolarak doğrular
Jeffz

13

Filter_var () kullanımı ascii olmayan karakterlere sahip url'ler için başarısız olur, örneğin ( http://pt.wikipedia.org/wiki/Guimarães ). Aşağıdaki işlev, filter_var () işlevini çağırmadan önce tüm ascii olmayan karakterleri (örneğin http://pt.wikipedia.org/wiki/Guimar%C3%A3es ) kodlar.

Umarım bu birine yardımcı olur.

<?php

function validate_url($url) {
    $path = parse_url($url, PHP_URL_PATH);
    $encoded_path = array_map('urlencode', explode('/', $path));
    $url = str_replace($path, implode('/', $encoded_path), $url);

    return filter_var($url, FILTER_VALIDATE_URL) ? true : false;
}

// example
if(!validate_url("http://somedomain.com/some/path/file1.jpg")) {
    echo "NOT A URL";
}
else {
    echo "IS A URL";
}

Budur. Sonunda biri 2017'de geri döndü
Kyle KIM

Benim için çalışıyor (diğerleri BTW değil) :)
Jono

Bu benim için işe yarayan TEK çözüm. Teşekkürler!
Silas

10
function is_url($uri){
    if(preg_match( '/^(http|https):\\/\\/[a-z0-9_]+([\\-\\.]{1}[a-z_0-9]+)*\\.[_a-z]{2,5}'.'((:[0-9]{1,5})?\\/.*)?$/i' ,$uri)){
      return $uri;
    }
    else{
        return false;
    }
}

3

Şahsen burada normal ifadeyi kullanmak istiyorum. Körük kodu benim için mükemmel çalıştı.

$baseUrl     = url('/'); // for my case https://www.xrepeater.com
$posted_url  = "home";
// Test with one by one
/*$posted_url  = "/home";
$posted_url  = "xrepeater.com";
$posted_url  = "www.xrepeater.com";
$posted_url  = "http://www.xrepeater.com";
$posted_url  = "https://www.xrepeater.com";
$posted_url  = "https://xrepeater.com/services";
$posted_url  = "xrepeater.dev/home/test";
$posted_url  = "home/test";*/

$regularExpression  = "((https?|ftp)\:\/\/)?"; // SCHEME Check
$regularExpression .= "([a-z0-9+!*(),;?&=\$_.-]+(\:[a-z0-9+!*(),;?&=\$_.-]+)?@)?"; // User and Pass Check
$regularExpression .= "([a-z0-9-.]*)\.([a-z]{2,3})"; // Host or IP Check
$regularExpression .= "(\:[0-9]{2,5})?"; // Port Check
$regularExpression .= "(\/([a-z0-9+\$_-]\.?)+)*\/?"; // Path Check
$regularExpression .= "(\?[a-z+&\$_.-][a-z0-9;:@&%=+\/\$_.-]*)?"; // GET Query String Check
$regularExpression .= "(#[a-z_.-][a-z0-9+\$_.-]*)?"; // Anchor Check

if(preg_match("/^$regularExpression$/i", $posted_url)) { 
    if(preg_match("@^http|https://@i",$posted_url)) {
        $final_url = preg_replace("@(http://)+@i",'http://',$posted_url);
        // return "*** - ***Match : ".$final_url;
    }
    else { 
          $final_url = 'http://'.$posted_url;
          // return "*** / ***Match : ".$final_url;
         }
    }
else {
     if (substr($posted_url, 0, 1) === '/') { 
         // return "*** / ***Not Match :".$final_url."<br>".$baseUrl.$posted_url;
         $final_url = $baseUrl.$posted_url;
     }
     else { 
         // return "*** - ***Not Match :".$posted_url."<br>".$baseUrl."/".$posted_url;
         $final_url = $baseUrl."/".$final_url; }
}

1
Bu, web sitelerinin URL'sini doğrulamak için en iyi cevaptır. Birkaç değişiklikle bu mükemmel çalışıyor. Teşekkürler
Amir hossein Karimi

3

Http: // gerektiren filter_var () ile ilgili sorunlar göz önüne alındığında, kullanıyorum:

$is_url = filter_var($filename, FILTER_VALIDATE_URL) || array_key_exists('scheme', parse_url($filename));


FILTER_VALIDATE_URL kullanmayın. Dağınık ve güvenilmez. Örneğin, geçerli ttps://www.youtube.comolarak doğrular
Jeffz

2

Bu işlevi kullanabilirsiniz, ancak web sitesi çevrimdışıysa yanlış döndürür.

  function isValidUrl($url) {
    $url = parse_url($url);
    if (!isset($url["host"])) return false;
    return !(gethostbyname($url["host"]) == $url["host"]);
}

2

Aslında ... filter_var ($ url, FILTER_VALIDATE_URL); çok iyi çalışmıyor. Gerçek bir url yazdığınızda çalışır, ancak yalnızca http: // olup olmadığını kontrol eder, bu nedenle " http: // weirtgcyaurbatc " gibi bir şey yazarsanız , yine de gerçek olduğunu söyleyecektir.


Kesinti için FILTER_VALIDATE_URL geçerli ttps://www.youtube.comolarak doğrular
Jeffz

1

Verilen URL'nin geçerli olup olmadığını kontrol etmenin bir başka yolu, ona erişmeye çalışmaktır, aşağıdaki işlev verilen URL'den başlıkları getirecektir, bu URL'nin geçerli olmasını VE web sunucusunun canlı olmasını sağlayacaktır :

function is_url($url){
        $response = array();
        //Check if URL is empty
        if(!empty($url)) {
            $response = get_headers($url);
        }
        return (bool)in_array("HTTP/1.1 200 OK", $response, true);
/*Array
(
    [0] => HTTP/1.1 200 OK 
    [Date] => Sat, 29 May 2004 12:28:14 GMT
    [Server] => Apache/1.3.27 (Unix)  (Red-Hat/Linux)
    [Last-Modified] => Wed, 08 Jan 2003 23:11:55 GMT
    [ETag] => "3f80f-1b6-3e1cb03b"
    [Accept-Ranges] => bytes
    [Content-Length] => 438
    [Connection] => close
    [Content-Type] => text/html
)*/ 
    }   

İyi fikir. Sunucu HTTP / 1.0 veya HTTP / 2.0 kullanıyorsa veya bir yönlendirme döndürüyorsa bu başarısız olur.
iblamefish

Evet, bu bir başlangıç ​​noktasıdır, daha fazla iyileştirme kolaylıkla yapılabilir.
Bud Damyanov

1

Rastladım bu makalede Bu hesap değişkenler dikkate alır 2012'den itibaren ya da olmayabilir sadece düz URL'ler.

Makalenin yazarı David Müeller , "... şansa değer olabilir" dediği bu işlevi, bazı örnekler filter_varve eksiklikleri ile birlikte sunmaktadır .

/**
 * Modified version of `filter_var`.
 *
 * @param  mixed $url Could be a URL or possibly much more.
 * @return bool
 */
function validate_url( $url ) {
    $url = trim( $url );

    return (
        ( strpos( $url, 'http://' ) === 0 || strpos( $url, 'https://' ) === 0 ) &&
        filter_var(
            $url,
            FILTER_VALIDATE_URL,
            FILTER_FLAG_SCHEME_REQUIRED || FILTER_FLAG_HOST_REQUIRED
        ) !== false
    );
}

0

Doğrulama için cURL kullanmak isteyen varsa. Aşağıdaki kodu kullanabilirsiniz.

<?php 
public function validationUrl($Url){
        if ($Url == NULL){
            return $false;
        }
        $ch = curl_init($Url);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $data = curl_exec($ch);
        $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        return ($httpcode >= 200 && $httpcode < 300) ? true : false; 
    }

0
public function testing($Url=''){
    $ch = curl_init($Url);
    curl_setopt($ch, CURLOPT_TIMEOUT, 5);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $data = curl_exec($ch);
    $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    if($httpcode >= 200 && $httpcode <= 301){
        $this->output->set_header('Access-Control-Allow-Origin: *');
        $this->output->set_content_type('application/json', 'utf-8');
        $this->output->set_status_header(200);
        $this->output->set_output(json_encode('VALID URL', JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
        return;
    }else{
        $this->output->set_header('Access-Control-Allow-Origin: *');
        $this->output->set_content_type('application/json', 'utf-8');
        $this->output->set_status_header(200);
        $this->output->set_output(json_encode('INVALID URL', JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
        return;
    }
}

Lütfen cevabınıza başkalarının öğrenebileceği bir açıklama ekleyin. Nereden $this->outputgeliyor?
Nico Haase
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.