URL에 대한 PHP 유효성 검사 / 정규식


125

URL에 대한 간단한 정규식을 찾고 있었는데, 잘 작동하는 편리한 사람이 있습니까? 나는 zend 프레임 워크 유효성 검사 클래스를 찾지 못했고 여러 구현을 보았습니다.


1
이것은 꽤 좋은 자원입니다. 다양한 패턴 및 테스트 목록을 제공합니다. mathiasbynens.be/demo/url-regex
omar j

답변:


79

나는 이것을 몇 가지 프로젝트에서 사용했지만 문제가 발생했다고 생각하지 않지만 철저하지 않다고 확신합니다.

$text = preg_replace(
  '#((https?|ftp)://(\S*?\.\S*?))([\s)\[\]{},;"\':<]|\.\s|$)#i',
  "'<a href=\"$1\" target=\"_blank\">$3</a>$4'",
  $text
);

마지막에 나오는 대부분의 무작위 쓰레기 http://domain.com.는 문장 과 같은 상황을 처리 하는 것입니다 (후행 마침표 일치를 피하기 위해). 나는 그것이 깨끗해질 수 있다고 확신하지만 그것이 효과가 있었기 때문에. 나는 프로젝트에서 프로젝트로 복사했습니다.


7
나에게 튀어 나온 몇 가지 : 문자 클래스가 호출되는 대체 사용 (모든 대체 문자가 정확히 한 문자와 일치 함); 그리고 대체는 외부 큰 따옴표가 필요하지 않아야합니다 (정규식의 무의미한 / e 수정 자 때문에 필요했습니다).
Alan Moore

1
@John Scipione : google.com은 유효한 상대 URL 경로 일 뿐이며 유효한 절대 URL이 아닙니다. 그리고 나는 그것이 그가 찾고있는 것이라고 생각합니다.
Gumbo

이것은이 경우에는 작업을하지 않습니다 - 그것은 후행 "을 포함 3 cantari 노이 albumul <a href=" audio.resursecrestine.ro/cantece/index-autori/andrei-rosu/...>
속는

1
@Softy http://example.com/somedir/...는 완전히 합법적 인 URL로, ...합법적 인 파일 이름 인- 라는 파일을 요청합니다 .
Stephen P

Zend \ Validator \ Regex를 사용하여 패턴을 사용하여 URL의 유효성을 검사하고 있지만 여전히 http://www.example유효한 것으로 감지 됩니다
Joko Wandiro 2013

207

filter_var()함수를 사용하여 문자열이 URL인지 여부를 확인합니다.

var_dump(filter_var('example.com', FILTER_VALIDATE_URL));

필요하지 않은 경우 정규식을 사용하는 것은 좋지 않습니다.

편집 : 조심하십시오.이 솔루션은 유니 코드 안전하지 않고 XSS 안전하지 않습니다. 복잡한 유효성 검사가 필요한 경우 다른 곳을 찾는 것이 좋습니다.


29
이 방법을 사용하여 대시가있는 URL의 유효성을 검사하지 못하게하는 5.2.13 (그리고 5.3.2라고 생각합니다)에 버그가 있습니다.
vamin 2010-06-01

14
filter_var는 test-site.com 을 거부 합니다. 도메인 이름이 유효한지 여부와 상관없이 대시가있는 도메인 이름이 있습니다. filter_var가 URL을 확인하는 가장 좋은 방법이라고 생각하지 않습니다. 그것은 같은 URL을 허용합니다http://www
Cesar

4
> ' www ' 와 같은 URL을 허용합니다. URL이 ' localhost ' 와 같은 경우 괜찮습니다
Stanislav

12
이 방법의 다른 문제는 유니 코드에 안전하지 않다는 것입니다.
Benji XVI

3
FILTER_VALIDATE_URL에는 수정이 필요한 많은 문제 가 있습니다. 또한 플래그를 설명 하는 문서 는 일부 플래그에 대한 참조가 완전히 제거 된 실제 소스 코드를 반영하지 않습니다 . 더 많은 정보 : news.php.net/php.internals/99018
S. Imp

29

PHP 매뉴얼에 따라 - parse_url해야 하지 URL을 확인하는 데 사용된다.

불행히도 filter_var('example.com', FILTER_VALIDATE_URL) 더 나은 성능을 하지 못하는 .

parse_url()및 둘 다 다음 과 filter_var()같은 잘못된 URL을 전달합니다.http://...

따라서이 경우 정규식 더 나은 방법입니다.


10
이 주장은 따르지 않습니다. FILTER_VALIDATE_URL이 원하는 것보다 조금 더 관대하다면 이러한 엣지 케이스를 처리하기 위해 몇 가지 추가 검사를 수행하십시오. URL에 대한 정규 표현식을 직접 시도하여 바퀴를 재발 명하는 것은 완전한 검사에서 더 멀어 질 것입니다.
Kzqai

2
직접 작성하지 않는 이유에 대한 예제는이 페이지의 모든 요약 정규식을 참조하십시오.
Kzqai

3
당신은 공정한 지적 Tchalvak를 만듭니다. URL과 같은 것에 대한 정규식은 (다른 응답에 따라) 올바르게 가져 오기가 매우 어려울 수 있습니다. 정규식이 항상 답은 아닙니다. 반대로 정규식이 항상 잘못된 답은 아닙니다. 중요한 점은 작업에 적합한 도구 (정규식 또는 기타)를 선택하고 구체적으로 "안티"또는 "프로"정규식이 아닌 것입니다. 돌이켜 보면 edge-case에 대한 제약 조건과 함께 filter_var를 사용하는 것에 대한 답변은 더 나은 답변처럼 보입니다 (특히 정규식 답변이 100 자
이상이

12

URL이 실제로 존재하는지 알고 싶은 경우 :

function url_exist($url){//se passar a URL existe
    $c=curl_init();
    curl_setopt($c,CURLOPT_URL,$url);
    curl_setopt($c,CURLOPT_HEADER,1);//get the header
    curl_setopt($c,CURLOPT_NOBODY,1);//and *only* get the header
    curl_setopt($c,CURLOPT_RETURNTRANSFER,1);//get the response as a string from curl_exec(), rather than echoing it
    curl_setopt($c,CURLOPT_FRESH_CONNECT,1);//don't use a cached version of the url
    if(!curl_exec($c)){
        //echo $url.' inexists';
        return false;
    }else{
        //echo $url.' exists';
        return true;
    }
    //$httpcode=curl_getinfo($c,CURLINFO_HTTP_CODE);
    //return ($httpcode<400);
}

1
$url위의 작업은 비용이 많이 들기 때문에 실제로 URL이 실제인지 확인하기 전에 일종의 유효성 검사를 수행 할 것입니다 . 파일 크기에 따라 200 밀리 초 정도 될 수 있습니다. 어떤 경우에는 URL에 아직 사용 가능한 위치에 리소스가 없을 수 있습니다 (예 : 아직 업로드되지 않은 이미지에 대한 URL 생성). 또한 캐시 된 버전을 사용하지 않으므로 file_exists()파일에 통계를 캐시하고 거의 즉시 반환합니다. 제공 한 솔루션은 여전히 ​​유용합니다. 왜 그냥 사용하지 fopen($url, 'r')않습니까?
Yzmir Ramirez 2011-08-06

고마워, 내가 찾던 바로 그것. 그러나 나는 그것을 사용하려고 실수를 저질렀다. 이 함수는 "url_exist"없습니다 "url_exists"죄송합니다 ;-)입니다
PJ 검은 머리

9
사용자가 입력 한 URL에 직접 액세스 할 경우 보안 위험이 있습니까?
siliconpi

404가 발견되면 확인을 추가하고 싶습니다. <code> $ httpCode = curl_getinfo ($ c, CURLINFO_HTTP_CODE); // echo $ url. ''. $ httpCode. '<br>'; if ($ httpCode == 404) {echo $ url. ' 404 '; } </ code>
Camaleo

전혀 안전하지 않습니다. 모든 입력 URL에 적극적으로 액세스합니다.
dmmd

11

John Gruber (Daring Fireball)에 따르면 :

정규식 :

(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))

preg_match ()에서 사용 :

preg_match("/(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))/", $url)

다음은 확장 정규식 패턴 (주석 포함)입니다.

(?xi)
\b
(                       # Capture 1: entire matched URL
  (?:
    https?://               # http or https protocol
    |                       #   or
    www\d{0,3}[.]           # "www.", "www1.", "www2." … "www999."
    |                           #   or
    [a-z0-9.\-]+[.][a-z]{2,4}/  # looks like domain name followed by a slash
  )
  (?:                       # One or more:
    [^\s()<>]+                  # Run of non-space, non-()<>
    |                           #   or
    \(([^\s()<>]+|(\([^\s()<>]+\)))*\)  # balanced parens, up to 2 levels
  )+
  (?:                       # End with:
    \(([^\s()<>]+|(\([^\s()<>]+\)))*\)  # balanced parens, up to 2 levels
    |                               #   or
    [^\s`!()\[\]{};:'".,<>?«»“”‘’]        # not a space or one of these punct chars
  )
)

자세한 내용은 http://daringfireball.net/2010/07/improved_regex_for_matching_urls를 참조하십시오.


9

이 경우 정규식을 사용하는 것이 현명한 일이라고 생각하지 않습니다. 모든 가능성을 일치시키는 것은 불가능하며 그렇게하더라도 URL이 단순히 존재하지 않을 가능성은 여전히 ​​있습니다.

다음은 URL이 실제로 존재하고 읽을 수 있는지 테스트하는 매우 간단한 방법입니다.

if (preg_match("#^https?://.+#", $link) and @fopen($link,"r")) echo "OK";

(없는 경우 preg_match서버의 모든 파일 이름도 확인합니다)


7

나는 이것을 성공적으로 사용했습니다. 어디서 얻었는지 기억이 나지 않습니다.

$pattern = "/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i";

^ (http : // | https : //)? (([a-z0-9]? ([-a-z0-9] * [a-z0-9] +)?) {1,63} \ .) + [az] {2,6} (너무 욕심이 많고 아직 확실하지 않지만 프로토콜과 선도적 인 www에서 더 유연함)
andrewbadera 2009-08-26

7
    function validateURL($URL) {
      $pattern_1 = "/^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i";
      $pattern_2 = "/^(www)((\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i";       
      if(preg_match($pattern_1, $URL) || preg_match($pattern_2, $URL)){
        return true;
      } else{
        return false;
      }
    }

'www.w3schools.com/home/3/?a=l'과 같은 링크에서는 작동하지 않습니다.
user3396065

5

그리고 당신의 대답이 있습니다 =) 그것을 깨려고 시도하십시오, 당신은 할 수 없습니다!

function link_validate_url($text) {
$LINK_DOMAINS = 'aero|arpa|asia|biz|com|cat|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel|mobi|local';
  $LINK_ICHARS_DOMAIN = (string) html_entity_decode(implode("", array( // @TODO completing letters ...
    "&#x00E6;", // æ
    "&#x00C6;", // Æ
    "&#x00C0;", // À
    "&#x00E0;", // à
    "&#x00C1;", // Á
    "&#x00E1;", // á
    "&#x00C2;", // Â
    "&#x00E2;", // â
    "&#x00E5;", // å
    "&#x00C5;", // Å
    "&#x00E4;", // ä
    "&#x00C4;", // Ä
    "&#x00C7;", // Ç
    "&#x00E7;", // ç
    "&#x00D0;", // Ð
    "&#x00F0;", // ð
    "&#x00C8;", // È
    "&#x00E8;", // è
    "&#x00C9;", // É
    "&#x00E9;", // é
    "&#x00CA;", // Ê
    "&#x00EA;", // ê
    "&#x00CB;", // Ë
    "&#x00EB;", // ë
    "&#x00CE;", // Î
    "&#x00EE;", // î
    "&#x00CF;", // Ï
    "&#x00EF;", // ï
    "&#x00F8;", // ø
    "&#x00D8;", // Ø
    "&#x00F6;", // ö
    "&#x00D6;", // Ö
    "&#x00D4;", // Ô
    "&#x00F4;", // ô
    "&#x00D5;", // Õ
    "&#x00F5;", // õ
    "&#x0152;", // Œ
    "&#x0153;", // œ
    "&#x00FC;", // ü
    "&#x00DC;", // Ü
    "&#x00D9;", // Ù
    "&#x00F9;", // ù
    "&#x00DB;", // Û
    "&#x00FB;", // û
    "&#x0178;", // Ÿ
    "&#x00FF;", // ÿ 
    "&#x00D1;", // Ñ
    "&#x00F1;", // ñ
    "&#x00FE;", // þ
    "&#x00DE;", // Þ
    "&#x00FD;", // ý
    "&#x00DD;", // Ý
    "&#x00BF;", // ¿
  )), ENT_QUOTES, 'UTF-8');

  $LINK_ICHARS = $LINK_ICHARS_DOMAIN . (string) html_entity_decode(implode("", array(
    "&#x00DF;", // ß
  )), ENT_QUOTES, 'UTF-8');
  $allowed_protocols = array('http', 'https', 'ftp', 'news', 'nntp', 'telnet', 'mailto', 'irc', 'ssh', 'sftp', 'webcal');

  // Starting a parenthesis group with (?: means that it is grouped, but is not captured
  $protocol = '((?:'. implode("|", $allowed_protocols) .'):\/\/)';
  $authentication = "(?:(?:(?:[\w\.\-\+!$&'\(\)*\+,;=" . $LINK_ICHARS . "]|%[0-9a-f]{2})+(?::(?:[\w". $LINK_ICHARS ."\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})*)?)?@)";
  $domain = '(?:(?:[a-z0-9' . $LINK_ICHARS_DOMAIN . ']([a-z0-9'. $LINK_ICHARS_DOMAIN . '\-_\[\]])*)(\.(([a-z0-9' . $LINK_ICHARS_DOMAIN . '\-_\[\]])+\.)*('. $LINK_DOMAINS .'|[a-z]{2}))?)';
  $ipv4 = '(?:[0-9]{1,3}(\.[0-9]{1,3}){3})';
  $ipv6 = '(?:[0-9a-fA-F]{1,4}(\:[0-9a-fA-F]{1,4}){7})';
  $port = '(?::([0-9]{1,5}))';

  // Pattern specific to external links.
  $external_pattern = '/^'. $protocol .'?'. $authentication .'?('. $domain .'|'. $ipv4 .'|'. $ipv6 .' |localhost)'. $port .'?';

  // Pattern specific to internal links.
  $internal_pattern = "/^(?:[a-z0-9". $LINK_ICHARS ."_\-+\[\]]+)";
  $internal_pattern_file = "/^(?:[a-z0-9". $LINK_ICHARS ."_\-+\[\]\.]+)$/i";

  $directories = "(?:\/[a-z0-9". $LINK_ICHARS ."_\-\.~+%=&,$'#!():;*@\[\]]*)*";
  // Yes, four backslashes == a single backslash.
  $query = "(?:\/?\?([?a-z0-9". $LINK_ICHARS ."+_|\-\.~\/\\\\%=&,$'():;*@\[\]{} ]*))";
  $anchor = "(?:#[a-z0-9". $LINK_ICHARS ."_\-\.~+%=&,$'():;*@\[\]\/\?]*)";

  // The rest of the path for a standard URL.
  $end = $directories .'?'. $query .'?'. $anchor .'?'.'$/i';

  $message_id = '[^@].*@'. $domain;
  $newsgroup_name = '(?:[0-9a-z+-]*\.)*[0-9a-z+-]*';
  $news_pattern = '/^news:('. $newsgroup_name .'|'. $message_id .')$/i';

  $user = '[a-zA-Z0-9'. $LINK_ICHARS .'_\-\.\+\^!#\$%&*+\/\=\?\`\|\{\}~\'\[\]]+';
  $email_pattern = '/^mailto:'. $user .'@'.'(?:'. $domain .'|'. $ipv4 .'|'. $ipv6 .'|localhost)'. $query .'?$/';

  if (strpos($text, '<front>') === 0) {
    return false;
  }
  if (in_array('mailto', $allowed_protocols) && preg_match($email_pattern, $text)) {
    return false;
  }
  if (in_array('news', $allowed_protocols) && preg_match($news_pattern, $text)) {
    return false;
  }
  if (preg_match($internal_pattern . $end, $text)) {
    return false;
  }
  if (preg_match($external_pattern . $end, $text)) {
    return false;
  }
  if (preg_match($internal_pattern_file, $text)) {
    return false;
  }

  return true;
}

더 많은 최상위 도메인이 있습니다.
Jeff Puckett 2016 년

4

편집 :
으로 발생 빈도는 지적이 코드는 PHP 5.3.0 (2009-06-30)의 출시와 함께 사용되지 않으며 그에 따라 사용되어야한다.


단지 2 센트이지만이 기능을 개발하여 한동안 성공적으로 사용하고 있습니다. 잘 문서화되고 분리되어 있으므로 쉽게 변경할 수 있습니다.

// Checks if string is a URL
// @param string $url
// @return bool
function isURL($url = NULL) {
    if($url==NULL) return false;

    $protocol = '(http://|https://)';
    $allowed = '([a-z0-9]([-a-z0-9]*[a-z0-9]+)?)';

    $regex = "^". $protocol . // must include the protocol
             '(' . $allowed . '{1,63}\.)+'. // 1 or several sub domains with a max of 63 chars
             '[a-z]' . '{2,6}'; // followed by a TLD
    if(eregi($regex, $url)==true) return true;
    else return false;
}

1
Eregi는 PHP 6.0.0에서 제거됩니다. 그리고 "öäåø"가있는 도메인은 귀하의 기능에 대해 검증되지 않습니다. URL을 먼저 퓨니 코드로 변환해야할까요?

@incidence는 절대적으로 동의합니다. 나는 3 월에 이것을 썼고 PHP 5.3은 6 월 말에 eregi를 DEPRECATED로 설정하여 나왔습니다. 감사합니다. 수정하고 업데이트하겠습니다.
Frankie

내가 틀렸다면 정정 해주세요.하지만 TLD가 최소 2 자에서 최대 6 자일 것이라고 가정 할 수 있습니까?
Yzmir Ramirez 2011 년

2
당신이 당신의 코멘트를 쓸 때 의심의 여지가 있었다면 @YzmirRamirez (이러한 모든 년 후 ...) 확실히 TLD와 함께, 지금이없는 등 .photography 이러한 일
닉 라이스

@NickRice 당신이 맞습니다 ... 5 년 동안 웹이 얼마나 변하는 지. 누군가가 TLD .supercalifragilisticexpialidocious하게 될 때까지 지금은 기다릴 수 없다
Yzmir 라미레즈

4
function is_valid_url ($url="") {

        if ($url=="") {
            $url=$this->url;
        }

        $url = @parse_url($url);

        if ( ! $url) {


            return false;
        }

        $url = array_map('trim', $url);
        $url['port'] = (!isset($url['port'])) ? 80 : (int)$url['port'];
        $path = (isset($url['path'])) ? $url['path'] : '';

        if ($path == '') {
            $path = '/';
        }

        $path .= ( isset ( $url['query'] ) ) ? "?$url[query]" : '';



        if ( isset ( $url['host'] ) AND $url['host'] != gethostbyname ( $url['host'] ) ) {
            if ( PHP_VERSION >= 5 ) {
                $headers = get_headers("$url[scheme]://$url[host]:$url[port]$path");
            }
            else {
                $fp = fsockopen($url['host'], $url['port'], $errno, $errstr, 30);

                if ( ! $fp ) {
                    return false;
                }
                fputs($fp, "HEAD $path HTTP/1.1\r\nHost: $url[host]\r\n\r\n");
                $headers = fread ( $fp, 128 );
                fclose ( $fp );
            }
            $headers = ( is_array ( $headers ) ) ? implode ( "\n", $headers ) : $headers;
            return ( bool ) preg_match ( '#^HTTP/.*\s+[(200|301|302)]+\s#i', $headers );
        }

        return false;
    }

안녕하세요,이 솔루션은 좋습니다. 저는 그것을 upvoted했지만 https의 표준 포트를 고려하지 않았습니다.-포트에서 작동하는 곳에서 80을 ''로 바꾸는 것이 좋습니다.
pgee70

내 도메인의 염려가 URL이 실제로 :)의 존재 여부 때문에 나는이의 변형을 구현 결국
Raz0rwire

2

이 .NET StackOverflow 질문해당 질문의이 참조 문서에서 영감을 얻었 습니다. (URI가이 URL과 URN 모두의 유효성을 확인 의미)이 URI 유효성 검사기가있다.

if( ! preg_match( "/^([a-z][a-z0-9+.-]*):(?:\\/\\/((?:(?=((?:[a-z0-9-._~!$&'()*+,;=:]|%[0-9A-F]{2})*))(\\3)@)?(?=(\\[[0-9A-F:.]{2,}\\]|(?:[a-z0-9-._~!$&'()*+,;=]|%[0-9A-F]{2})*))\\5(?::(?=(\\d*))\\6)?)(\\/(?=((?:[a-z0-9-._~!$&'()*+,;=:@\\/]|%[0-9A-F]{2})*))\\8)?|(\\/?(?!\\/)(?=((?:[a-z0-9-._~!$&'()*+,;=:@\\/]|%[0-9A-F]{2})*))\\10)?)(?:\\?(?=((?:[a-z0-9-._~!$&'()*+,;=:@\\/?]|%[0-9A-F]{2})*))\\11)?(?:#(?=((?:[a-z0-9-._~!$&'()*+,;=:@\\/?]|%[0-9A-F]{2})*))\\12)?$/i", $uri ) )
{
    throw new \RuntimeException( "URI has not a valid format." );
}

내가 만든 ValueObject 내 에서이 함수를 성공적으로 단위 테스트했습니다. Uri 테스트했습니다.UriTest .

UriTest.php (URL과 URN 모두에 대해 유효하고 유효하지 않은 케이스 포함)

<?php

declare( strict_types = 1 );

namespace XaviMontero\ThrasherPortage\Tests\Tour;

use XaviMontero\ThrasherPortage\Tour\Uri;

class UriTest extends \PHPUnit_Framework_TestCase
{
    private $sut;

    public function testCreationIsOfProperClassWhenUriIsValid()
    {
        $sut = new Uri( 'http://example.com' );
        $this->assertInstanceOf( 'XaviMontero\\ThrasherPortage\\Tour\\Uri', $sut );
    }

    /**
     * @dataProvider urlIsValidProvider
     * @dataProvider urnIsValidProvider
     */
    public function testGetUriAsStringWhenUriIsValid( string $uri )
    {
        $sut = new Uri( $uri );
        $actual = $sut->getUriAsString();

        $this->assertInternalType( 'string', $actual );
        $this->assertEquals( $uri, $actual );
    }

    public function urlIsValidProvider()
    {
        return
            [
                [ 'http://example-server' ],
                [ 'http://example.com' ],
                [ 'http://example.com/' ],
                [ 'http://subdomain.example.com/path/?parameter1=value1&parameter2=value2' ],
                [ 'random-protocol://example.com' ],
                [ 'http://example.com:80' ],
                [ 'http://example.com?no-path-separator' ],
                [ 'http://example.com/pa%20th/' ],
                [ 'ftp://example.org/resource.txt' ],
                [ 'file://../../../relative/path/needs/protocol/resource.txt' ],
                [ 'http://example.com/#one-fragment' ],
                [ 'http://example.edu:8080#one-fragment' ],
            ];
    }

    public function urnIsValidProvider()
    {
        return
            [
                [ 'urn:isbn:0-486-27557-4' ],
                [ 'urn:example:mammal:monotreme:echidna' ],
                [ 'urn:mpeg:mpeg7:schema:2001' ],
                [ 'urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66' ],
                [ 'rare-urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66' ],
                [ 'urn:FOO:a123,456' ]
            ];
    }

    /**
     * @dataProvider urlIsNotValidProvider
     * @dataProvider urnIsNotValidProvider
     */
    public function testCreationThrowsExceptionWhenUriIsNotValid( string $uri )
    {
        $this->expectException( 'RuntimeException' );
        $this->sut = new Uri( $uri );
    }

    public function urlIsNotValidProvider()
    {
        return
            [
                [ 'only-text' ],
                [ 'http//missing.colon.example.com/path/?parameter1=value1&parameter2=value2' ],
                [ 'missing.protocol.example.com/path/' ],
                [ 'http://example.com\\bad-separator' ],
                [ 'http://example.com|bad-separator' ],
                [ 'ht tp://example.com' ],
                [ 'http://exampl e.com' ],
                [ 'http://example.com/pa th/' ],
                [ '../../../relative/path/needs/protocol/resource.txt' ],
                [ 'http://example.com/#two-fragments#not-allowed' ],
                [ 'http://example.edu:portMustBeANumber#one-fragment' ],
            ];
    }

    public function urnIsNotValidProvider()
    {
        return
            [
                [ 'urn:mpeg:mpeg7:sch ema:2001' ],
                [ 'urn|mpeg:mpeg7:schema:2001' ],
                [ 'urn?mpeg:mpeg7:schema:2001' ],
                [ 'urn%mpeg:mpeg7:schema:2001' ],
                [ 'urn#mpeg:mpeg7:schema:2001' ],
            ];
    }
}

Uri.php (값 개체)

<?php

declare( strict_types = 1 );

namespace XaviMontero\ThrasherPortage\Tour;

class Uri
{
    /** @var string */
    private $uri;

    public function __construct( string $uri )
    {
        $this->assertUriIsCorrect( $uri );
        $this->uri = $uri;
    }

    public function getUriAsString()
    {
        return $this->uri;
    }

    private function assertUriIsCorrect( string $uri )
    {
        // /programming/30847/regex-to-validate-uris
        // http://snipplr.com/view/6889/regular-expressions-for-uri-validationparsing/

        if( ! preg_match( "/^([a-z][a-z0-9+.-]*):(?:\\/\\/((?:(?=((?:[a-z0-9-._~!$&'()*+,;=:]|%[0-9A-F]{2})*))(\\3)@)?(?=(\\[[0-9A-F:.]{2,}\\]|(?:[a-z0-9-._~!$&'()*+,;=]|%[0-9A-F]{2})*))\\5(?::(?=(\\d*))\\6)?)(\\/(?=((?:[a-z0-9-._~!$&'()*+,;=:@\\/]|%[0-9A-F]{2})*))\\8)?|(\\/?(?!\\/)(?=((?:[a-z0-9-._~!$&'()*+,;=:@\\/]|%[0-9A-F]{2})*))\\10)?)(?:\\?(?=((?:[a-z0-9-._~!$&'()*+,;=:@\\/?]|%[0-9A-F]{2})*))\\11)?(?:#(?=((?:[a-z0-9-._~!$&'()*+,;=:@\\/?]|%[0-9A-F]{2})*))\\12)?$/i", $uri ) )
        {
            throw new \RuntimeException( "URI has not a valid format." );
        }
    }
}

UnitTests 실행

46 개의 테스트에 65 개의 주장이 있습니다. 주의 : 유효한 데이터 제공자는 2 개, 유효하지 않은 표현식에는 2 개가 더 있습니다. 하나는 URL 용이고 다른 하나는 URN 용입니다. PhpUnit v5.6 * 이전 버전을 사용하는 경우 두 데이터 공급자를 단일 공급자로 결합해야합니다.

xavi@bromo:~/custom_www/hello-trip/mutant-migrant$ vendor/bin/phpunit
PHPUnit 5.7.3 by Sebastian Bergmann and contributors.

..............................................                    46 / 46 (100%)

Time: 82 ms, Memory: 4.00MB

OK (46 tests, 65 assertions)

코드 커버리지

이 샘플 URI 검사기에는 코드 커버리지가 100 % 있습니다.


2
"/(http(s?):\/\/)([a-z0-9\-]+\.)+[a-z]{2,4}(\.[a-z]{2,4})*(\/[^ ]+)*/i"
  1. (http (s?) : //)는 http : // 또는 https : //를 의미합니다.

  2. ([a-z0-9-] +.) + => 2.0 [a-z0-9-]는 모든 z 문자 또는 모든 0-9 또는 (-) 기호를 의미합니다.

                 2.1 (+) means the character can be one or more ex: a1w, 
                     a9-,c559s, f)
    
                 2.2 \. is (.)sign
    
                 2.3. the (+) sign after ([a-z0-9\-]+\.) mean do 2.1,2.2,2.3 
                    at least 1 time 
                  ex: abc.defgh0.ig, aa.b.ced.f.gh. also in case www.yyy.com
    
                 3.[a-z]{2,4} mean a-z at least 2 character but not more than 
                              4 characters for check that there will not be 
                              the case 
                              ex: https://www.google.co.kr.asdsdagfsdfsf
    
                 4.(\.[a-z]{2,4})*(\/[^ ]+)* mean 
    
                   4.1 \.[a-z]{2,4} means like number 3 but start with 
                       (.)sign 
    
                   4.2 * means (\.[a-z]{2,4})can be use or not use never mind
    
                   4.3 \/ means \
                   4.4 [^ ] means any character except blank
                   4.5 (+) means do 4.3,4.4,4.5 at least 1 times
                   4.6 (*) after (\/[^ ]+) mean use 4.3 - 4.5 or not use 
                       no problem
    
                   use for case https://stackoverflow.com/posts/51441301/edit
    
                   5. when you use regex write in "/ /" so it come

    "/(http(s?)://)([a-z0-9-]+.)+[az]{2,4}(.[az]{2,4}) (/ [^] + ) / i "

                   6. almost forgot: letter i on the back mean ignore case of 
                      Big letter or small letter ex: A same as a, SoRRy same 
                      as sorry.

참고 : 영어가 안 좋아서 죄송합니다. 우리나라는 잘 사용하지 않습니다.


4
이 질문이 몇 살인지 눈치 채 셨나요? 정규식을 설명해주세요. 아직 모르는 사용자는 세부 사항 없이는 이해하기 어려울 것입니다.
Nic3500

1

좋아요, 이것은 간단한 정규식보다 조금 더 복잡하지만 다른 유형의 URL을 허용합니다.

예 :

유효한 것으로 표시되어야하는 모든 것.

function is_valid_url($url) {
    // First check: is the url just a domain name? (allow a slash at the end)
    $_domain_regex = "|^[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(\.[A-Za-z]{2,})/?$|";
    if (preg_match($_domain_regex, $url)) {
        return true;
    }

    // Second: Check if it's a url with a scheme and all
    $_regex = '#^([a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))$#';
    if (preg_match($_regex, $url, $matches)) {
        // pull out the domain name, and make sure that the domain is valid.
        $_parts = parse_url($url);
        if (!in_array($_parts['scheme'], array( 'http', 'https' )))
            return false;

        // Check the domain using the regex, stops domains like "-example.com" passing through
        if (!preg_match($_domain_regex, $_parts['host']))
            return false;

        // This domain looks pretty valid. Only way to check it now is to download it!
        return true;
    }

    return false;
}

허용하려는 프로토콜에 대한 in_array 검사가 있습니다 (현재는 http 및 https 만 해당 목록에 있음).

var_dump(is_valid_url('google.com'));         // true
var_dump(is_valid_url('google.com/'));        // true
var_dump(is_valid_url('http://google.com'));  // true
var_dump(is_valid_url('http://google.com/')); // true
var_dump(is_valid_url('https://google.com')); // true

오류 : ErrorException : 정의되지 않은 인덱스 : 프로토콜이 지정되지 않은 경우 스키마가 이전에 설정되었는지 확인하는 것이 좋습니다.
user3396065

@ user3396065, 이것을 던지는 예제 입력을 제공 할 수 있습니까?
Tim Groeneveld

1

나를 위해 일한 최고의 URL 정규식 :

function valid_URL($url){
    return preg_match('%^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@|\d{1,3}(?:\.\d{1,3}){3}|(?:(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)(?:\.(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)*(?:\.[a-z\x{00a1}-\x{ffff}]{2,6}))(?::\d+)?(?:[^\s]*)?$%iu', $url);
}

예 :

valid_URL('https://twitter.com'); // true
valid_URL('http://twitter.com');  // true
valid_URL('http://twitter.co');   // true
valid_URL('http://t.co');         // true
valid_URL('http://twitter.c');    // false
valid_URL('htt://twitter.com');   // false

valid_URL('http://example.com/?a=1&b=2&c=3'); // true
valid_URL('http://127.0.0.1');    // true
valid_URL('');                    // false
valid_URL(1);                     // false

출처 : http://urlregex.com/


0

Peter 's Regex는 여러 가지 이유로 나에게 옳지 않은 것 같습니다. 도메인 이름에 모든 종류의 특수 문자를 허용하며 많이 테스트하지 않습니다.

Frankie의 함수는 나에게 좋아 보이며 함수를 원하지 않으면 다음과 같이 구성 요소에서 좋은 정규식을 만들 수 있습니다.

^(http://|https://)(([a-z0-9]([-a-z0-9]*[a-z0-9]+)?){1,63}\.)+[a-z]{2,6}

테스트되지 않았지만 작동해야한다고 생각합니다.

또한 Owen의 답변도 100 %로 보이지 않습니다. 정규식의 도메인 부분을 가져 와서 정규식 테스터 도구 http://erik.eae.net/playground/regexp/regexp.html 에서 테스트했습니다 .

다음 줄을 넣습니다.

(\S*?\.\S*?)

"regexp"섹션과 다음 행에서 :

-hello.com

"샘플 텍스트"섹션 아래에 있습니다.

그 결과 마이너스 문자가 허용되었습니다. \ S는 공백이 아닌 문자를 의미하기 때문입니다.

Frankie의 정규식은 첫 번째 문자에 대해 다음 부분이 있기 때문에 마이너스를 처리합니다.

[a-z0-9]

마이너스 또는 기타 특수 문자를 허용하지 않습니다.


0

내가 한 방법은 다음과 같습니다. 그러나 나는 정규식에 대해 그렇게 확신하지 않는 멘토 인을 원합니다. 그러나 그것은 당신이 작동해야합니다 :)

$pattern = "#((http|https)://(\S*?\.\S*?))(\s|\;|\)|\]|\[|\{|\}|,|”|\"|'|:|\<|$|\.\s)#i";
        $text = preg_replace_callback($pattern,function($m){
                return "<a href=\"$m[1]\" target=\"_blank\">$m[1]</a>$m[4]";
            },
            $text);

이렇게하면 패턴에 평가 마커가 필요하지 않습니다.

도움이되기를 바랍니다 :)


0

다음은 URL 유효성 검사를 위한 간단한 클래스입니다. RegEx를 사용한 인기있는 RBL (실시간 블랙홀 목록) 서버에 대해 도메인을 상호 참조합니다.

설치:

require 'URLValidation.php';

용법:

require 'URLValidation.php';
$urlVal = new UrlValidation(); //Create Object Instance

domain()메소드 의 매개 변수로 URL을 추가 하고 리턴을 확인하십시오.

$urlArray = ['http://www.bokranzr.com/test.php?test=foo&test=dfdf', 'https://en-gb.facebook.com', 'https://www.google.com'];
foreach ($urlArray as $k=>$v) {

    echo var_dump($urlVal->domain($v)) . ' URL: ' . $v . '<br>';

}

산출:

bool(false) URL: http://www.bokranzr.com/test.php?test=foo&test=dfdf
bool(true) URL: https://en-gb.facebook.com
bool(true) URL: https://www.google.com

위에서 볼 수 있듯이 www.bokranzr.com은 RBL을 통해 악성 웹 사이트로 분류되어 도메인이 거짓으로 반환되었습니다.



-1

URL 일치에 가장 유용하다는 것을 알았습니다 ..

^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$

1
로 시작하는 URL과 일치 ftp:합니까?
andrewsi

/^(https?:\/\/)?([\da-z\.-]+)\.([az\.]{2,6})([\/\w \ .-] *) * \ /? $ /
Shahbaz 2013 년

-1

이를위한 PHP 기본 기능이 있습니다.

$url = 'http://www.yoururl.co.uk/sub1/sub2/?param=1&param2/';

if ( ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
    // Wrong
}
else {
    // Valid
}

필터링 된 데이터를 반환하거나 필터가 실패하면 FALSE를 반환합니다.

여기에서 확인하세요


이 답변은 2008 년 답변 중 하나와 중복됩니다!
Suspectus
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.