Convalida / regex PHP per URL


125

Ho cercato una semplice regex per gli URL, qualcuno ne ha uno a portata di mano che funzioni bene? Non ne ho trovato uno con le classi di convalida del framework zend e ho visto diverse implementazioni.


1
Questa è una buona risorsa. Fornisce un elenco di molti modelli e test diversi: mathiasbynens.be/demo/url-regex
omar j

Risposte:


79

L'ho usato su alcuni progetti, non credo di aver riscontrato problemi, ma sono sicuro che non sia esaustivo:

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

La maggior parte della spazzatura casuale alla fine è affrontare situazioni come http://domain.com.in una frase (per evitare di abbinare il punto finale). Sono sicuro che potrebbe essere ripulito ma dal momento che ha funzionato. L'ho copiato più o meno da un progetto all'altro.


7
Alcune cose che mi vengono in mente: uso dell'alternanza in cui sono richieste classi di caratteri (ogni alternativa corrisponde esattamente a un carattere); e la sostituzione non avrebbe dovuto richiedere le virgolette esterne (erano necessarie solo a causa dell'inutile modificatore / e sulla regex).
Alan Moore

1
@ John Scipione: google.comè solo un percorso URL relativo valido ma non un URL assoluto valido. E penso che sia quello che sta cercando.
Gumbo

Questo non funziona in questo caso - che include il finale ": 3 cantari noi in albumul <a href=" audio.resursecrestine.ro/cantece/index-autori/andrei-rosu/...>
Softy

1
@Softy qualcosa di simile http://example.com/somedir/...è un URL perfettamente legittimo, che richiede il file denominato ..., che è un nome file legittimo.
Stephen P

Sto usando Zend \ Validator \ Regex per convalidare l'URL usando il tuo pattern, ma rileva ancora http://www.exampledi essere valido
Joko Wandiro

207

Utilizza la filter_var()funzione per verificare se una stringa è URL o meno:

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

È una cattiva pratica usare espressioni regolari quando non è necessario.

EDIT : fai attenzione, questa soluzione non è sicura per unicode e non sicura per XSS. Se hai bisogno di una convalida complessa, forse è meglio cercare altrove.


29
C'è un bug nella 5.2.13 (e credo 5.3.2) che impedisce la convalida degli URL con trattini utilizzando questo metodo.
vamin

14
filter_var rifiuterà test-site.com , ho nomi di dominio con trattini, indipendentemente dal fatto che siano validi o meno. Non penso che filter_var sia il modo migliore per convalidare un URL. Consentirà un URL comehttp://www
Cesar

4
> Consentirà un URL come " www " Va bene quando un URL come " localhost "
Stanislav

12
L'altro problema con questo metodo è che non è sicuro per unicode.
Benji XVI

3
FILTER_VALIDATE_URL ha molti problemi che devono essere risolti . Inoltre, i documenti che descrivono i flag non riflettono il codice sorgente effettivo in cui i riferimenti ad alcuni flag sono stati completamente rimossi. Maggiori info qui: news.php.net/php.internals/99018
S. Imp

29

Secondo il manuale PHP, parse_url non dovrebbe essere usato per convalidare un URL.

Sfortunatamente, sembra che filter_var('example.com', FILTER_VALIDATE_URL)non funzioni meglio.

Entrambi parse_url()e filter_var()passeranno URL non corretti comehttp://...

Pertanto in questo caso - regex è il metodo migliore.


10
Questo argomento non segue. Se FILTER_VALIDATE_URL è un po 'più permissivo di quanto desideri, aggiungi alcuni controlli aggiuntivi per gestire questi casi limite. Reinventare la ruota con il tuo tentativo di eseguire una regex contro gli URL ti porterà solo più lontano da un controllo completo.
Kzqai

2
Vedi tutte le espressioni regolari abbattute su questa pagina per esempi del perché -non- scriverne una tua.
Kzqai

3
Tchalvak hai ragione. Le espressioni regolari per qualcosa come gli URL possono (come per altre risposte) essere molto difficili da ottenere correttamente. Regex non è sempre la risposta. Al contrario, anche la regex non è sempre la risposta sbagliata. Il punto importante è scegliere lo strumento giusto (regex o altro) per il lavoro e non essere specificamente regex "anti" o "pro". Col senno di poi, la tua risposta sull'uso di filter_var in combinazione con i vincoli sui casi limite, sembra la risposta migliore (in particolare quando le risposte regex iniziano ad arrivare a più di 100 caratteri o giù di lì - rendendo il mantenimento di detta regex un incubo)
catchdave

12

Nel caso tu voglia sapere se l'URL esiste davvero:

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
Vorrei comunque eseguire un qualche tipo di convalida $urlprima di verificare effettivamente che l'URL sia reale perché l'operazione sopra è costosa, forse fino a 200 millisecondi a seconda della dimensione del file. In alcuni casi, l'URL potrebbe non avere ancora una risorsa nella sua posizione disponibile (ad esempio, creando un URL per un'immagine che deve ancora essere caricata). Inoltre non stai utilizzando una versione memorizzata nella cache, quindi non è così file_exists()che memorizzerà una statistica su un file e tornerà quasi istantaneamente. La soluzione che hai fornito è comunque utile. Perché non basta usare fopen($url, 'r')?
Yzmir Ramirez

Grazie, proprio quello che stavo cercando. Tuttavia, ho commesso un errore cercando di usarlo. La funzione è "url_exist" non "url_exists" oops ;-)
PJ Brunet

9
Esiste un rischio per la sicurezza nell'accesso diretto all'URL inserito dall'utente?
siliconpi

vorresti aggiungere un controllo se è stato trovato un 404: <code> $ httpCode = curl_getinfo ($ c, CURLINFO_HTTP_CODE); // echo $ url. ''. $ httpCode. '<br>'; if ($ httpCode == 404) {echo $ url. ' 404' ; } </code>
Camaleo

Non è affatto sicuro ... si accederà attivamente a qualsiasi URL di input.
dmmd

11

Secondo 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`!()\[\]{};:'\".,<>?«»“”‘’]))

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

Ecco il pattern regex esteso (con commenti):

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

Per maggiori dettagli, visita : http://daringfireball.net/2010/07/improved_regex_for_matching_urls


9

Non penso che l'uso di espressioni regolari sia una cosa intelligente da fare in questo caso. È impossibile abbinare tutte le possibilità e anche se lo facessi, c'è ancora la possibilità che l'URL semplicemente non esista.

Ecco un modo molto semplice per verificare se l'URL esiste effettivamente ed è leggibile:

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

(se non c'è, preg_matchquesto convaliderà anche tutti i nomi di file sul tuo server)


7

L'ho usato con buon successo - non ricordo da dove l'ho preso

$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} (potrebbe essere troppo avido, non ancora sicuro, ma è più flessibile sul protocollo e sul www principale)
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;
      }
    }

Non funziona con link come: "www.w3schools.com/home/3/?a=l"
user3396065

5

Ed ecco la tua risposta =) Prova a romperlo, non puoi !!!

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

Ci sono molti più domini di primo livello .
Jeff Puckett

4

Modifica:
come ha sottolineato l' incidenza , questo codice è stato DEPRECATO con il rilascio di PHP 5.3.0 (2009-06-30) e dovrebbe essere utilizzato di conseguenza.


Solo i miei due centesimi ma ho sviluppato questa funzione e la uso da tempo con successo. È ben documentato e separato, quindi puoi cambiarlo facilmente.

// 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 verrà rimosso in PHP 6.0.0. E i domini con "öäåø" non verranno convalidati con la tua funzione. Probabilmente dovresti prima convertire l'URL in punycode?

@incidence assolutamente d'accordo. L'ho scritto a marzo e PHP 5.3 è uscito solo a fine giugno impostando eregi come DEPRECATO. Grazie. Devo modificare e aggiornare.
Frankie

Correggimi se sbaglio, ma possiamo comunque presumere che i TLD abbiano un minimo di 2 caratteri e un massimo di 6 caratteri?
Yzmir Ramirez

2
@YzmirRamirez (Tutti questi anni dopo ...) Se c'erano dei dubbi quando hai scritto il tuo commento, di certo non ce ne sono ora, con TLD in questi giorni come .photography
Nick Rice

@ NickRice hai ragione ... quanto cambia il web in 5 anni. Ora non vedo l'ora che qualcuno crei il 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;
    }

Ciao, questa soluzione è buona e l'ho votata in più, ma non tiene conto della porta standard per https: - ti suggerisco di sostituire 80 con '' dove funziona la porta
pgee70

Ho finito per implementare una variazione su questo, perché al mio dominio importa se un URL esiste effettivamente o meno :)
Raz0rwire

2

Ispirato in questa domanda .NET StackOverflow e in questo articolo di riferimento da quella domanda, c'è questo validatore URI (URI significa che convalida sia l'URL che l'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." );
}

Ho testato con successo questa funzione all'interno di un ValueObject che ho nominato Urie testato da UriTest.

UriTest.php (contiene casi validi e non validi sia per gli URL che per gli 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 (oggetto valore)

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

Esecuzione di test unitari

Ci sono 65 affermazioni in 46 test. Attenzione: ci sono 2 fornitori di dati per espressioni valide e altri 2 per espressioni non valide. Uno è per gli URL e l'altro per gli URN. Se stai utilizzando una versione di PhpUnit v5.6 * o precedente, devi unire i due fornitori di dati in uno solo.

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)

Copertura del codice

C'è il 100% di copertura del codice in questo controllo URI di esempio.


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

  2. ([a-z0-9 -] +.) + => 2.0 [a-z0-9-] significa qualsiasi carattere az o qualsiasi segno 0-9 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”{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.

Nota: ci scusiamo per il cattivo inglese. Il mio paese non lo usa bene.


4
Hai notato quanti anni ha questa domanda? Spiega la tua regex, gli utenti che non lo sanno già avranno difficoltà a capirlo senza dettagli.
Nic3500

1

OK, quindi questo è un po 'più complesso di una semplice regex, ma consente diversi tipi di URL.

Esempi:

Tutto ciò dovrebbe essere contrassegnato come valido.

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

Si noti che è presente un controllo in_array per i protocolli che si desidera consentire (attualmente solo http e https sono nell'elenco).

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

Produce: ErrorException: Indice non definito: schema se il protocollo non è specificato suggerisco di controllare se è impostato prima.
user3396065

@ user3396065, puoi fornire un input di esempio che generi questo?
Tim Groeneveld

1

Il miglior URL Regex che ha funzionato per me:

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

Esempi:

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

Fonte: http://urlregex.com/


0

Il Regex di Peter non mi sembra giusto per molte ragioni. Permette tutti i tipi di caratteri speciali nel nome di dominio e non verifica molto.

La funzione di Frankie mi sembra buona e puoi creare una buona regex dai componenti se non vuoi una funzione, in questo modo:

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

Non testato ma penso che dovrebbe funzionare.

Inoltre, neanche la risposta di Owen sembra al 100%. Ho preso la parte del dominio della regex e l'ho testata su uno strumento tester Regex http://erik.eae.net/playground/regexp/regexp.html

Metto la seguente riga:

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

nella sezione "regexp" e nella riga seguente:

-hello.com

nella sezione "testo di esempio".

Il risultato ha consentito il passaggio del carattere meno. Perché \ S significa qualsiasi carattere non spazio.

Nota che la regex di Frankie gestisce il meno perché ha questa parte per il primo carattere:

[a-z0-9]

Che non consentirà il meno o qualsiasi altro carattere speciale.


0

Ecco come l'ho fatto. Ma voglio dire che non sono così sicuro della regex. Ma dovrebbe funzionare tu :)

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

In questo modo non avrai bisogno del pennarello eval sul tuo pattern.

Spero che sia d'aiuto :)


0

Ecco una semplice classe per la convalida dell'URL utilizzando RegEx e quindi i riferimenti incrociati del dominio con i server RBL (Realtime Blackhole Lists) popolari:

Installare:

require 'URLValidation.php';

Uso:

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

Aggiungi un URL come parametro del domain()metodo e controlla il ritorno.

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

}

Produzione:

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

Come puoi vedere sopra, www.bokranzr.com è elencato come sito Web dannoso tramite un RBL, quindi il dominio è stato restituito come falso.



-1

Ho trovato che questo è il più utile per la corrispondenza di un URL ..

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

1
Corrisponderà agli URL che iniziano con ftp:?
andrewsi

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

-1

Esiste una funzione nativa PHP per questo:

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

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

Restituisce i dati filtrati o FALSE se il filtro non riesce.

Controlla qui


Questa risposta duplica una delle risposte del 2008!
suspectus
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.