Лучший способ проверить, действителен ли URL


149

Я хочу использовать PHP, чтобы проверить, $myoutputсодержит ли строка, хранящаяся в переменной, правильный синтаксис ссылки или это просто обычный текст. Функция или решение, которое я ищу, должно распознавать все форматы ссылок, в том числе с параметрами GET.

Решение, предложенное на многих сайтах, на самом деле запросить строку (используя CURL или file_get_contents()функцию) в моем случае невозможно, и я бы хотел этого избежать.

Я думал о регулярных выражениях или другом решении.


Использование CURL или получение его содержимого HTTP может быть медленным, если вы хотите что-то более быстрое и почти такое же надежное, рассмотрите возможность использования gethostbyaddr () в имени хоста. Если он разрешается на IP, то, вероятно, у него есть веб-сайт. Конечно это зависит от ваших потребностей.
TravisO

Ответы:


301

Вы можете использовать собственный фильтр Validator

filter_var($url, FILTER_VALIDATE_URL);

Проверяет значение как URL (в соответствии с » http://www.faqs.org/rfcs/rfc2396 ), возможно, с необходимыми компонентами. Осторожно, допустимый URL может не указывать HTTP-протокол http: //, поэтому может потребоваться дополнительная проверка, чтобы определить, использует ли URL ожидаемый протокол, например, ssh: // или mailto :. Обратите внимание, что функция найдет только действительные URL-адреса ASCII; интернационализированные доменные имена (содержащие не-ASCII символы) потерпят неудачу.

Пример:

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

9
Ожидаемое поведение @Raveren, так как это допустимые URL.
Гордон

8
Имейте в FILTER_VALIDATE_URLвиду, что не будет проверять протокол URL. Так ssh://и ftp://тд пройдет.
Seph

3
@SephVelut ожидаемое поведение, так как это действительные URL.
Гордон

1
он позволяет URL-адреса, такие как ttp: //amazon.com
Elia Weiss

4
@JoshHabdas, я думаю, ты упускаешь суть. Код PHP делает именно то, что заявляет. Но это не может читать ваши мысли. Существует огромная разница между недопустимым и нежелательным. Нежелательный - это очень субъективно, поэтому программисту предстоит проработать эту деталь. Вы также можете заметить, что код проверяет URL, но не доказывает, что он существует. Не вина PHP в том, что пользователь неправильно набрал «амазон», «амозон», что подтвердит правильность, но все еще нежелательно.
JBH

20

Вот лучший урок, который я нашел там:

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

Возможные флаги:

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

1
Просто гнида: !filter_var(...) === false==> filter_var(...) === trueили просто filter_var(...). :)
Доменико Де Феличе,

@ ErichGarcía этот код не проверяет, является ли он действующим URL-адресом HTTP / S, как запрашивает OP. Это передаст такие вещи, как ssh: //, ftp: // и т. Д., Он только проверяет, является ли его синтаксически действительный URL-адрес в соответствии с RFC 2396
twigg

Не используйте FILTER_VALIDATE_URL. Это грязно и ненадежно. Например, он подтверждается ttps://www.youtube.comкак действительный
Джеффз

12

Использование filter_var () не удастся для URL с символами, отличными от ascii, например ( http://pt.wikipedia.org/wiki/Guimarães ). Следующая функция кодирует все символы, отличные от ascii (например, http://pt.wikipedia.org/wiki/Guimar%C3%A3es ) перед вызовом filter_var ().

Надеюсь, это кому-нибудь поможет.

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

Это оно. Наконец кто-то вернулся в 2017 году
Кайл КИМ

Работает для меня (другие не BTW) :)
Jono

Это единственное решение, которое сработало для меня. Спасибо!
Сайлас

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

Лично я хотел бы использовать регулярное выражение здесь. Сильфонный код отлично сработал для меня.

$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
Это лучший ответ для проверки URL сайтов. С небольшими изменениями эта работа отлично. Спасибо
Амир Хоссейн Карими

3

Учитывая проблемы с filter_var (), требующие http: //, я использую:

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


Не используйте FILTER_VALIDATE_URL. Это грязно и ненадежно. Например, это подтверждается ttps://www.youtube.comкак действительное
Джеффз

2

Вы можете использовать эту функцию, но она вернет false, если сайт отключен.

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

2

На самом деле ... filter_var ($ url, FILTER_VALIDATE_URL); не очень хорошо работает Когда вы вводите реальный URL, он работает, но проверяет только http: //, поэтому, если вы наберете что-то вроде « http: // weirtgcyaurbatc », он все равно скажет, что это реально.


Для примера, FILTER_VALIDATE_URL подтверждается ttps://www.youtube.comкак действительный
Jeffz

1

Другой способ проверить , если данный URL действует, чтобы попытаться получить к нему доступ, ниже функции будет получать заголовки из данного URL, это будет гарантировать , что URL является действительным и веб - сервер жив:

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
)*/ 
    }   

Хорошая идея. Это не удастся, если сервер использует HTTP / 1.0 или HTTP / 2.0 или вернет перенаправление.
iblamefish

Да, это отправная точка, дальнейшие улучшения могут быть сделаны легко.
Буд Дамьянов

1

Наткнулся на эту статью с 2012 года. Он учитывает переменные, которые могут быть или не быть просто обычными URL.

Автор статьи, Дэвид Мюллер , предлагает эту функцию, которая, по его словам, «... может стоить хитрости», наряду с некоторыми примерами filter_varи ее недостатками.

/**
 * 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

если кто-то заинтересован использовать cURL для проверки. Вы можете использовать следующий код.

<?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; 
    }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.