Xác thực / regex cho URL


125

Tôi đã tìm kiếm một regex đơn giản cho các URL, có ai có một tiện ích nào hoạt động tốt không? Tôi đã không tìm thấy một lớp với các lớp xác nhận khung zend và đã thấy một số triển khai.


1
Đây là một nguồn tài nguyên khá tốt. Cung cấp một danh sách rất nhiều mẫu và bài kiểm tra khác nhau: mathiasbynens.be/demo/url-regex
omar j

Câu trả lời:


79

Tôi đã sử dụng điều này trong một vài dự án, tôi không tin rằng tôi đã gặp phải vấn đề, nhưng tôi chắc chắn rằng nó không đầy đủ:

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

Hầu hết các rác ngẫu nhiên ở cuối là để xử lý các tình huống như http://domain.com.trong câu (để tránh khớp với khoảng thời gian kéo dài). Tôi chắc chắn rằng nó có thể được làm sạch nhưng vì nó hoạt động. Tôi đã ít nhiều chỉ sao chép nó từ dự án này sang dự án khác.


7
Một số thứ nhảy ra khỏi tôi: sử dụng xen kẽ trong đó các lớp nhân vật được yêu cầu (mỗi phương án thay thế khớp chính xác một ký tự); và sự thay thế không cần phải có dấu ngoặc kép bên ngoài (chúng chỉ cần thiết vì công cụ sửa đổi vô nghĩa / e trên regex).
Alan Moore

1
@John Scipione: google.comchỉ là đường dẫn URL tương đối hợp lệ nhưng không phải là URL tuyệt đối hợp lệ. Và tôi nghĩ đó là những gì anh ấy đang tìm kiếm.
Gumbo

Đây không phải làm việc trong trường hợp này - nó bao gồm các dấu ": 3 cantari noi trong albumul <a href=" audio.resursecrestine.ro/cantece/index-autori/andrei-rosu/...>
softy

1
@Softy một cái gì đó giống như http://example.com/somedir/...một URL hoàn toàn hợp pháp, yêu cầu tệp có tên ...- đó là tên tệp hợp pháp.
Stephen P

Tôi đang sử dụng Zend \ Validator \ Regex để xác thực url bằng mẫu của bạn, nhưng nó vẫn phát hiện http://www.examplelà hợp lệ
Joko Wandiro

207

Sử dụng filter_var()hàm để xác thực xem một chuỗi có phải là URL hay không:

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

Đó là thực tế xấu để sử dụng các biểu thức thông thường khi không cần thiết.

EDIT : Hãy cẩn thận, giải pháp này không an toàn unicode và không an toàn XSS. Nếu bạn cần một xác nhận phức tạp, có lẽ tốt hơn là tìm một nơi khác.


29
Có một lỗi trong 5.2.13 (và tôi nghĩ 5.3.2) ngăn các url có dấu gạch ngang trong chúng xác thực bằng phương thức này.
vamin

14
filter_var sẽ từ chối test-site.com , tôi có tên miền có dấu gạch ngang, chúng có hợp lệ hay không. Tôi không nghĩ rằng bộ lọc_var là cách tốt nhất để xác thực một url. Nó sẽ cho phép một url nhưhttp://www
Cesar

4
> Nó sẽ cho phép một url như ' www ' Sẽ ổn khi URL như ' localhost '
Stanislav

12
Vấn đề khác với phương pháp này là nó không an toàn.
Benji XVI

3
FILTER_VALIDATE_URL có rất nhiều vấn đề cần khắc phục. Ngoài ra, các tài liệu mô tả các cờ không phản ánh mã nguồn thực tế nơi các tham chiếu đến một số cờ đã bị xóa hoàn toàn. Thêm thông tin tại đây: news.php.net/php.iternals/99018
S. Imp

29

Theo hướng dẫn PHP - không nên sử dụng parse_url để xác thực URL.

Thật không may, có vẻ như filter_var('example.com', FILTER_VALIDATE_URL)không thực hiện tốt hơn.

Cả hai parse_url()filter_var()sẽ vượt qua các URL không đúng định dạng, chẳng hạn nhưhttp://...

Do đó trong trường hợp này - regex phương pháp tốt hơn.


10
Đối số này không tuân theo. Nếu FILTER_VALIDATE_URL dễ dàng hơn một chút so với mong muốn của bạn, hãy giải quyết một số kiểm tra bổ sung để xử lý các trường hợp cạnh đó. Phát minh lại bánh xe với nỗ lực của chính bạn trong một regex chống lại các url chỉ giúp bạn tiến xa hơn từ một kiểm tra hoàn chỉnh.
Kzqai

2
Xem tất cả các biểu thức rút gọn trên trang này để biết ví dụ về lý do tại sao -không- để viết riêng của bạn.
Kzqai

3
Bạn làm một điểm công bằng Tchalvak. Các quy tắc cho một cái gì đó như URL có thể (theo các phản hồi khác) rất khó để có được quyền. Regex không phải lúc nào cũng là câu trả lời. Ngược lại, regex cũng không phải lúc nào cũng là câu trả lời sai. Điểm quan trọng là chọn đúng công cụ (regex hoặc cách khác) cho công việc và không được cụ thể là regex "chống" hoặc "pro". Nhìn nhận lại, câu trả lời của bạn về việc sử dụng bộ lọc_var kết hợp với các ràng buộc đối với các trường hợp cạnh của nó, có vẻ như câu trả lời tốt hơn (đặc biệt là khi các câu trả lời regex bắt đầu lớn hơn 100 ký tự - làm cho việc bảo trì regex nói trên trở thành cơn ác mộng)
bắt kịp

12

Chỉ trong trường hợp bạn muốn biết nếu url thực sự tồn tại:

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
Tôi vẫn sẽ thực hiện một số loại xác thực $urltrước khi thực sự xác minh url là có thật vì thao tác trên rất tốn kém - có thể lên tới 200 mili giây tùy thuộc vào kích thước tệp. Trong một số trường hợp, url có thể chưa thực sự có sẵn tài nguyên tại vị trí của nó (ví dụ: tạo url cho hình ảnh chưa được tải lên). Ngoài ra, bạn không sử dụng phiên bản được lưu trong bộ nhớ cache nên không giống như file_exists()vậy sẽ lưu trữ một chỉ số trên một tệp và trả về gần như ngay lập tức. Các giải pháp bạn cung cấp vẫn hữu ích mặc dù. Tại sao không chỉ sử dụng fopen($url, 'r')?
Yzmir Ramirez

Cảm ơn, chỉ là những gì tôi đang tìm kiếm. Tuy nhiên, tôi đã phạm sai lầm khi cố gắng sử dụng nó. Chức năng là "url_exist" chứ không phải "url_exists" oops ;-)
PJ Brunet

9
Có bất kỳ rủi ro bảo mật nào khi truy cập trực tiếp URL người dùng đã nhập không?
siliconpi

bạn muốn thêm một kiểm tra nếu tìm thấy 404: <code> $ httpCode = curl_getinfo ($ c, CURLINEFO_HTTP_CODE); // lặp lại $ url. ''. $ httpCode. '<br>'; if ($ httpCode == 404) {echo $ url. ' 404 '; } </ code>
Camaleo

Không an toàn chút nào .. mọi URL đầu vào sẽ được truy cập tích cực.
dmmd

11

Theo John Gruber (Daring Fireball):

Chế độ:

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

sử dụng trong 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)

Đây là mẫu regex mở rộng (có ý kiến):

(?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
  )
)

Để biết thêm chi tiết xin vui lòng xem tại: http://daredfireball.net/2010/07/improved_regex_for_matching_urls


9

Tôi không nghĩ rằng sử dụng các biểu thức thông thường là một điều thông minh để làm trong trường hợp này. Không thể phù hợp với tất cả các khả năng và ngay cả khi bạn đã làm, vẫn có khả năng url đơn giản là không tồn tại.

Đây là một cách rất đơn giản để kiểm tra xem url có thực sự tồn tại và có thể đọc được không:

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

(nếu không có preg_matchthì điều này cũng sẽ xác nhận tất cả tên tệp trên máy chủ của bạn)


7

Tôi đã sử dụng cái này với thành công tốt - tôi không nhớ tôi đã lấy nó từ đâu

$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} (có thể quá tham lam, chưa chắc chắn, nhưng nó linh hoạt hơn về giao thức và dẫn đầu www)
andrewbadera

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

Không hoạt động với liên kết như: 'www.w3schools.com/home/3/?a=l'
user3396065

5

Và có câu trả lời của bạn =) Hãy thử phá vỡ nó, bạn không thể !!!

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


4

Chỉnh sửa:
Như tỷ lệ đã chỉ ra mã này đã bị ĐỔI với việc phát hành PHP 5.3.0 (2009-06-30) và nên được sử dụng tương ứng.


Chỉ hai xu của tôi nhưng tôi đã phát triển chức năng này và đã sử dụng nó được một thời gian với thành công. Nó được ghi chép tốt và tách biệt để bạn có thể dễ dàng thay đổi nó.

// 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 sẽ bị xóa trong PHP 6.0.0. Và các miền có "öäåø" sẽ không xác thực với chức năng của bạn. Bạn có lẽ nên chuyển đổi URL thành Punycode trước?

@incidence hoàn toàn đồng ý. Tôi đã viết cái này vào tháng 3 và PHP 5.3 chỉ xuất hiện vào cuối tháng 6 với tên là TIẾP TỤC. Cảm ơn bạn. Gonna chỉnh sửa và cập nhật.
Frankie

Chỉnh sửa cho tôi nếu tôi sai, nhưng chúng ta vẫn có thể giả sử TLD sẽ có tối thiểu 2 ký tự và tối đa là 6 ký tự không?
Yzmir Ramirez

2
@YzmirRamirez (Tất cả những năm sau ...) Nếu có bất kỳ nghi ngờ gì nữa khi bạn đã viết bình luận của bạn có chắc chắn không phải là bây giờ, với TLD những ngày này như .photography
Nick Rice

@NickRice bạn đúng ... web thay đổi bao nhiêu trong 5 năm. Bây giờ tôi không thể đợi cho đến khi ai đó thực hiện TLD .supercalifragilisticexpialidocious
Yzmir Ramirez

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

Xin chào, giải pháp này rất tốt và tôi đã nâng cấp nó, nhưng nó không tính đến cổng tiêu chuẩn cho https: - đề nghị bạn chỉ cần thay thế 80 bằng '' nơi nó hoạt động ngoài cổng
pgee70


2

Lấy cảm hứng trong câu hỏi .NET StackOverflow nàytrong bài viết được tham chiếu từ câu hỏi này có trình xác nhận URI này (URI có nghĩa là nó xác nhận cả URL và URN).

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

Tôi đã kiểm tra đơn vị thành công chức năng này bên trong một ValueObject mà tôi đã đặt tên Urivà kiểm tra bởi UriTest.

UriTest.php (Chứa các trường hợp hợp lệ và không hợp lệ cho cả URL và 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 (Đối tượng giá trị)

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

Chạy UnitTests

Có 65 khẳng định trong 46 bài kiểm tra. Thận trọng: có 2 nhà cung cấp dữ liệu hợp lệ và 2 nhà cung cấp dữ liệu không hợp lệ. Một là cho URL và cái còn lại cho URN. Nếu bạn đang sử dụng phiên bản PhpUnit của v5.6 * trở về trước thì bạn cần tham gia hai nhà cung cấp dữ liệu vào một phiên bản duy nhất.

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)

Mã số bảo hiểm

Có 100% phạm vi bảo hiểm mã trong trình kiểm tra URI mẫu này.


2
"/(http(s?):\/\/)([a-z0-9\-]+\.)+[a-z]{2,4}(\.[a-z]{2,4})*(\/[^ ]+)*/i"
  1. (http (s?): //) có nghĩa là http: // hoặc https: //

  2. ([a-z0-9 -] +.) + => 2.0 [a-z0-9-] có nghĩa là bất kỳ ký tự az hoặc bất kỳ dấu 0-9 hoặc (-) nào)

                 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[ đũa2,4spl (.[ az[ đũa2,4}) (/ [^] + ) / tô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.

Lưu ý: Xin lỗi vì tiếng Anh không tốt. Đất nước tôi không sử dụng tốt.


4
Bạn có để ý câu hỏi này bao nhiêu tuổi không? Vui lòng giải thích regex của bạn, người dùng chưa biết sẽ khó hiểu về nó mà không có chi tiết.
Nic3500

1

OK, vì vậy đây là một chút phức tạp hơn một regex đơn giản, nhưng nó cho phép các loại url khác nhau.

Ví dụ:

Tất cả những gì cần được đánh dấu là hợp lệ.

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

Lưu ý rằng có một kiểm tra in_array cho các giao thức mà bạn muốn cho phép (hiện tại chỉ có http và https nằm trong danh sách đó).

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

Ném: ErrorException: Index không xác định: lược đồ nếu giao thức không được chỉ định tôi đề nghị kiểm tra nếu được đặt trước.
dùng3396065

@ user3396065, bạn có thể vui lòng cung cấp một ví dụ đầu vào ném cái này không?
Tim Groeneveld

1

Regex URL tốt nhất hoạt động với tôi:

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

Ví dụ:

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

Nguồn: http://urlregex.com/


0

Regex của Peter không phù hợp với tôi vì nhiều lý do. Nó cho phép tất cả các loại ký tự đặc biệt trong tên miền và không kiểm tra nhiều.

Chức năng của Frankie có vẻ tốt với tôi và bạn có thể xây dựng một regex tốt từ các thành phần nếu bạn không muốn một chức năng, như vậy:

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

Chưa được kiểm tra nhưng tôi nghĩ rằng nên làm việc.

Ngoài ra, câu trả lời của Owen cũng không giống 100%. Tôi đã lấy phần miền của regex và thử nghiệm nó trên công cụ kiểm tra Regex http://erik.eae.net/playground/regapi/regapid.html

Tôi đặt dòng sau:

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

trong phần "regrec" và dòng sau:

-hello.com

trong phần "văn bản mẫu".

Kết quả cho phép nhân vật trừ qua. Bởi vì \ S có nghĩa là bất kỳ ký tự không phải không gian.

Lưu ý regex từ Frankie xử lý điểm trừ vì nó có phần này cho ký tự đầu tiên:

[a-z0-9]

Mà sẽ không cho phép trừ hoặc bất kỳ nhân vật đặc biệt nào khác.


0

Đây là cách tôi đã làm nó. Nhưng tôi muốn mentoin rằng tôi không quá chắc chắn về regex. Nhưng nó nên hoạt động :)

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

Bằng cách này, bạn sẽ không cần điểm đánh dấu trên mẫu của bạn.

Hy vọng nó giúp :)


0

Đây là một lớp đơn giản để xác thực URL bằng RegEx và sau đó tham chiếu chéo tên miền với các máy chủ RBL (Danh sách lỗ đen thời gian thực) phổ biến:

Tải về:

require 'URLValidation.php';

Sử dụng:

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

Thêm một URL làm tham số của domain()phương thức và kiểm tra trả về.

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

}

Đầu ra:

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

Như bạn có thể thấy ở trên, www.bokranzr.com được liệt kê là trang web độc hại thông qua RBL để tên miền được trả về là sai.



-1

Tôi thấy điều này hữu ích nhất để khớp URL ..

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

1
Điều đó có khớp với các URL bắt đầu bằng ftp:không?
andrewsi

/ ^ ^ / tpsps: * \ /? $ /
Shahbaz

-1

Có một hàm riêng cho PHP:

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

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

Trả về dữ liệu đã lọc hoặc FALSE nếu bộ lọc bị lỗi.

Kiểm tra nó ở đây


Câu trả lời này trùng lặp một trong những câu trả lời từ năm 2008!
suspectus
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.