PHP-Validierung / Regex für URL

125

Ich habe nach einem einfachen regulären Ausdruck für URLs gesucht. Hat jemand einen zur Hand, der gut funktioniert? Ich habe keine mit den Validierungsklassen des zend-Frameworks gefunden und mehrere Implementierungen gesehen.

AndreLiem
quelle
1
Dies ist eine ziemlich gute Ressource. Gibt eine Liste mit vielen verschiedenen Mustern und Tests: mathiasbynens.be/demo/url-regex
omar j

Antworten:

79

Ich habe dies bei einigen Projekten verwendet. Ich glaube nicht, dass ich auf Probleme gestoßen bin, aber ich bin sicher, dass es nicht erschöpfend ist:

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

Der größte Teil des zufälligen Mülls am Ende besteht darin, Situationen wie http://domain.com.in einem Satz zu behandeln (um zu vermeiden, dass die nachfolgende Periode übereinstimmt). Ich bin sicher, es könnte aufgeräumt werden, aber da es funktioniert hat. Ich habe es mehr oder weniger einfach von Projekt zu Projekt kopiert.

Owen
quelle
7
Einige Dinge, die mir auffallen: Verwendung der Abwechslung, bei der Zeichenklassen erforderlich sind (jede Alternative entspricht genau einem Zeichen); und der Ersatz hätte die äußeren doppelten Anführungszeichen nicht benötigen sollen (sie wurden nur wegen des sinnlosen / e-Modifikators auf der Regex benötigt).
Alan Moore
1
@ John Scipione: google.comist nur ein gültiger relativer URL-Pfad, aber keine gültige absolute URL. Und ich denke, das ist es, wonach er sucht.
Gumbo
Das funktioniert nicht in diesem Fall - es den nachgestellten „beinhaltet: 3 Cantari noi in albumul <a href=" audio.resursecrestine.ro/cantece/index-autori/andrei-rosu/...>
Softy
1
@Softy so etwas http://example.com/somedir/...ist eine absolut legitime URL, die nach der benannten Datei fragt ...- was ein legitimer Dateiname ist.
Stephen P
Ich benutze Zend \ Validator \ Regex, um die URL anhand Ihres Musters zu validieren, aber es wird immer noch http://www.exampleals gültig
erkannt
207

Verwenden Sie die filter_var()Funktion, um zu überprüfen, ob eine Zeichenfolge eine URL ist oder nicht:

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

Es ist eine schlechte Praxis, reguläre Ausdrücke zu verwenden, wenn dies nicht erforderlich ist.

EDIT : Seien Sie vorsichtig, diese Lösung ist nicht Unicode-sicher und nicht XSS-sicher. Wenn Sie eine komplexe Validierung benötigen, ist es vielleicht besser, woanders zu suchen.

Stanislav
quelle
29
Es gibt einen Fehler in 5.2.13 (und ich denke 5.3.2), der verhindert, dass URLs mit Bindestrichen mit dieser Methode überprüft werden.
Vamin
14
filter_var lehnt test-site.com ab . Ich habe Domain-Namen mit Bindestrichen, ob sie gültig sind oder nicht. Ich denke nicht, dass filter_var der beste Weg ist, eine URL zu validieren. Es wird eine URL wiehttp://www
Cesar
4
> Es erlaubt eine URL wie ' www '. Es ist in Ordnung, wenn URL wie ' localhost '
Stanislav
12
Das andere Problem bei dieser Methode ist, dass sie nicht unicode-sicher ist.
Benji XVI
3
FILTER_VALIDATE_URL hat viele Probleme , die behoben werden müssen. Außerdem spiegeln die Dokumente, die die Flags beschreiben , nicht den tatsächlichen Quellcode wider , bei dem Verweise auf einige Flags vollständig entfernt wurden. Weitere Infos hier: news.php.net/php.internals/99018
S. Imp
29

Gemäß dem PHP-Handbuch sollte parse_url nicht zum Überprüfen einer URL verwendet werden.

Leider scheint das filter_var('example.com', FILTER_VALIDATE_URL)nicht besser zu funktionieren.

Beide parse_url()und filter_var()übergeben fehlerhafte URLs wiehttp://...

Daher wird in diesem Fall - regex ist die bessere Methode.

catchdave
quelle
10
Dieses Argument folgt nicht. Wenn FILTER_VALIDATE_URL etwas freizügiger ist als Sie möchten, führen Sie einige zusätzliche Überprüfungen durch, um diese Randfälle zu behandeln. Wenn Sie das Rad mit Ihrem eigenen Versuch einer Regex gegen URLs neu erfinden, kommen Sie nur noch weiter von einer vollständigen Überprüfung.
Kzqai
2
In allen abgeschossenen regulären Ausdrücken auf dieser Seite finden Sie Beispiele dafür, warum Sie nicht Ihre eigenen schreiben sollten.
Kzqai
3
Sie machen einen fairen Punkt Tchalvak. Regexes für so etwas wie URLs können (wie bei anderen Antworten) sehr schwer zu finden sein. Regex ist nicht immer die Antwort. Umgekehrt ist Regex auch nicht immer die falsche Antwort. Der wichtige Punkt ist, das richtige Werkzeug (Regex oder auf andere Weise) für den Job auszuwählen und nicht speziell "Anti" - oder "Pro" -Regex zu sein. Im Nachhinein scheint Ihre Antwort, filter_var in Kombination mit Einschränkungen für die Randfälle zu verwenden, die bessere Antwort zu sein (insbesondere, wenn Regex-Antworten mehr als 100 Zeichen erreichen - was die Wartung dieses Regex zu einem Albtraum macht)
catchdave
12

Nur für den Fall, dass Sie wissen möchten, ob die URL wirklich existiert:

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);
}
Roger
quelle
1
Ich würde immer noch eine Art Validierung durchführen, $urlbevor ich tatsächlich überprüfe, ob die URL echt ist, da der oben genannte Vorgang teuer ist - je nach Dateigröße vielleicht bis zu 200 Millisekunden. In einigen Fällen ist für die URL möglicherweise noch keine Ressource an ihrem Speicherort verfügbar (z. B. Erstellen einer URL für ein Bild, das noch hochgeladen werden muss). Außerdem verwenden Sie keine zwischengespeicherte Version, sodass file_exists()eine Statistik nicht in einer Datei zwischengespeichert und fast sofort zurückgegeben wird. Die von Ihnen bereitgestellte Lösung ist jedoch weiterhin nützlich. Warum nicht einfach benutzen fopen($url, 'r')?
Yzmir Ramirez
Danke, genau das, wonach ich gesucht habe. Ich habe jedoch einen Fehler gemacht, als ich versucht habe, es zu verwenden. Die Funktion ist "url_exist" nicht "url_exists" oops ;-)
PJ Brunet
9
Gibt es ein Sicherheitsrisiko beim direkten Zugriff auf die vom Benutzer eingegebene URL?
Siliconpi
Sie möchten eine Überprüfung hinzufügen, ob ein 404 gefunden wurde: <code> $ httpCode = curl_getinfo ($ c, CURLINFO_HTTP_CODE); // echo $ url. ''. $ httpCode. '<br>'; if ($ httpCode == 404) {echo $ url. ' 404 '; } </ code>
Camaleo
Ist überhaupt nicht sicher. Auf jede Eingabe-URL wird aktiv zugegriffen.
dmmd
11

Nach John Gruber (Daring Fireball):

Regex:

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

using in 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)

Hier ist das erweiterte Regex-Muster (mit Kommentaren):

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

Weitere Informationen finden Sie unter: http://daringfireball.net/2010/07/improved_regex_for_matching_urls

abhiomkar
quelle
9

Ich denke nicht, dass die Verwendung regulärer Ausdrücke in diesem Fall eine kluge Sache ist. Es ist unmöglich, alle Möglichkeiten zu nutzen, und selbst wenn Sie dies getan haben, besteht immer noch die Möglichkeit, dass die URL einfach nicht existiert.

Hier ist eine sehr einfache Möglichkeit, um zu testen, ob die URL tatsächlich vorhanden und lesbar ist:

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

(Wenn preg_matchdies nicht der Fall ist, werden auch alle Dateinamen auf Ihrem Server überprüft.)

promaty
quelle
7

Ich habe dieses mit gutem Erfolg verwendet - ich erinnere mich nicht, woher ich es habe

$pattern = "/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i";
Peter Bailey
quelle
^ (http: // | https: //)? (([a-z0-9]? ([-a-z0-9] * [a-z0-9] +)?) {1,63} \ .) + [az] {2,6} (mag zu gierig sein, noch nicht sicher, aber es ist flexibler in
Bezug
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;
      }
    }
Vikash Kumar
quelle
Funktioniert nicht mit Link wie: 'www.w3schools.com/home/3/?a=l'
user3396065
5

Und da ist deine Antwort =) Versuche es zu brechen, du kannst nicht !!!

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;
}
George Milonas
quelle
Es gibt viel mehr Top-Level-Domains .
Jeff Puckett
4

Bearbeiten:
Wie die Inzidenz hervorhob, wurde dieser Code mit der Veröffentlichung von PHP 5.3.0 (30.06.2009) VERRINGERT und sollte entsprechend verwendet werden.


Nur meine zwei Cent, aber ich habe diese Funktion entwickelt und benutze sie seit einiger Zeit mit Erfolg. Es ist gut dokumentiert und getrennt, so dass Sie es leicht ändern können.

// 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;
}
Frankie
quelle
1
Eregi wird in PHP 6.0.0 entfernt. Und Domains mit "öäåø" werden mit Ihrer Funktion nicht validiert. Sie sollten wahrscheinlich zuerst die URL in Punycode konvertieren?
@ Zufall absolut einverstanden. Ich habe dies im März geschrieben und PHP 5.3 kam erst Ende Juni heraus und stellte eregi als DEPRECATED ein. Danke dir. Wird bearbeitet und aktualisiert.
Frankie
Korrigieren Sie mich, wenn ich falsch liege. Können wir dennoch davon ausgehen, dass TLDs mindestens 2 Zeichen und höchstens 6 Zeichen enthalten?
Yzmir Ramirez
2
@YzmirRamirez (All diese Jahre später ...) Wenn es Zweifel gab, als Sie Ihren Kommentar geschrieben haben, gibt es jetzt sicherlich keine, mit TLDs in diesen Tagen wie .photography
Nick Rice
@NickRice Sie haben Recht ... wie sehr sich das Web in 5 Jahren verändert. Jetzt kann ich nicht warten, bis jemand die TLD .supercalifragilisticexpialidocious macht
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;
    }
jini
quelle
Hallo, diese Lösung ist gut, und ich habe sie positiv bewertet, aber sie berücksichtigt nicht den Standardport für https: - Schlagen Sie vor, Sie ersetzen nur 80 durch '', wo der Port
funktioniert
Am Ende habe ich eine Variation implementiert, weil meine Domain sich
darum
2

Inspiriert von dieser .NET StackOverflow-Frage und in diesem Artikel, auf den in dieser Frage verwiesen wird, gibt es diesen URI-Validator (URI bedeutet, dass sowohl URL als auch URN validiert werden).

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

Ich habe diese Funktion erfolgreich in einem von mir benannten Uriund getesteten ValueObject getestet UriTest.

UriTest.php (Enthält gültige und ungültige Fälle für URLs und URNs)

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

<?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 ausführen

Es gibt 65 Aussagen in 46 Tests. Achtung: Es gibt 2 Datenanbieter für gültige und 2 weitere für ungültige Ausdrücke. Eine ist für URLs und die andere für URNs. Wenn Sie eine Version von PhpUnit von Version 5.6 * oder früher verwenden, müssen Sie die beiden Datenanbieter zu einem einzigen verbinden.

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)

Codeabdeckung

In diesem URI-Beispielprüfer ist die Codeabdeckung zu 100% vorhanden.

Xavi Montero
quelle
2
"/(http(s?):\/\/)([a-z0-9\-]+\.)+[a-z]{2,4}(\.[a-z]{2,4})*(\/[^ ]+)*/i"
  1. (http (s?): //) bedeutet http: // oder https: //

  2. ([a-z0-9 -] +.) + => 2,0 [a-z0-9-] bedeutet ein beliebiges Az-Zeichen oder ein 0-9- oder (-) Zeichen)

                 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- lightboxes + ) / 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.

Hinweis: Entschuldigung für schlechtes Englisch. Mein Land nutzt es nicht gut.

Some_North_korea_kid
quelle
4
Haben Sie bemerkt, wie alt diese Frage ist? Bitte erläutern Sie Ihren regulären Ausdruck. Benutzer, die dies noch nicht wissen, werden Schwierigkeiten haben, ihn ohne Details zu verstehen.
Nic3500
1

OK, das ist ein bisschen komplexer als ein einfacher Regex, aber es erlaubt verschiedene Arten von URLs.

Beispiele:

Alles, was als gültig markiert werden sollte.

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

Beachten Sie, dass für die Protokolle, die Sie zulassen möchten, eine In_array-Prüfung durchgeführt wird (derzeit befinden sich nur http und https in dieser Liste).

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
Tim Groeneveld
quelle
Auslöser: ErrorException: Undefinierter Index: Schema, wenn das Protokoll nicht angegeben ist. Ich schlage vor, zu überprüfen, ob es zuvor festgelegt wurde.
user3396065
@ user3396065, können Sie bitte eine Beispieleingabe angeben, die dies auslöst?
Tim Groeneveld
1

Die beste URL Regex, die für mich funktioniert hat:

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

Beispiele:

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

Quelle: http://urlregex.com/

Fred Vanelli
quelle
0

Peters Regex sieht für mich aus vielen Gründen nicht richtig aus. Es erlaubt alle Arten von Sonderzeichen im Domain-Namen und testet nicht viel.

Frankies Funktion sieht für mich gut aus und Sie können aus den Komponenten einen guten regulären Ausdruck erstellen, wenn Sie keine Funktion möchten, wie folgt:

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

Ungetestet, aber ich denke, das sollte funktionieren.

Auch Owens Antwort sieht nicht 100% aus. Ich habe den Domain-Teil des Regex genommen und ihn mit einem Regex-Tester-Tool http://erik.eae.net/playground/regexp/regexp.html getestet

Ich setze die folgende Zeile:

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

im Abschnitt "Regexp" und in der folgenden Zeile:

-hello.com

unter dem Abschnitt "Beispieltext".

Das Ergebnis ließ das Minuszeichen durch. Weil \ S ein beliebiges Nicht-Leerzeichen bedeutet.

Beachten Sie, dass der reguläre Ausdruck von Frankie das Minus behandelt, da er diesen Teil für das erste Zeichen enthält:

[a-z0-9]

Was das Minuszeichen oder ein anderes Sonderzeichen nicht zulässt.

Joedevon
quelle
0

Hier ist, wie ich es gemacht habe. Aber ich möchte erwähnen, dass ich in Bezug auf die Regex nicht so sicher bin. Aber es sollte funktionieren du :)

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

Auf diese Weise benötigen Sie den Bewertungsmarker nicht auf Ihrem Muster.

Ich hoffe es hilft :)

Thomas Venturini
quelle
0

Hier ist eine einfache Klasse für die URL-Validierung mit RegEx, in der die Domain mit gängigen RBL-Servern (Realtime Blackhole Lists) verglichen wird:

Installieren:

require 'URLValidation.php';

Verwendung:

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

Fügen Sie eine URL als Parameter der domain()Methode hinzu und überprüfen Sie die Rückgabe.

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

}

Ausgabe:

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

Wie Sie oben sehen können, wird www.bokranzr.com über eine RBL als schädliche Website aufgeführt, sodass die Domain als falsch zurückgegeben wurde.

Kitson88
quelle
-1

Ich habe festgestellt, dass dies am nützlichsten ist, um eine URL abzugleichen.

^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$
Jeremy Moore
quelle
1
Entspricht das URLs, die mit beginnen ftp:?
Andrewsi
/^(https?:\/\/)?([\da-z\.- weibl. +). * \ /? $ /
Shahbaz
-1

Dafür gibt es eine native PHP-Funktion:

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

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

Gibt die gefilterten Daten zurück oder FALSE, wenn der Filter fehlschlägt.

Überprüfen Sie es hier

Fredmat
quelle
Diese Antwort dupliziert eine der Antworten aus dem Jahr 2008!
Verdächtiger