Проверка PHP / регулярное выражение для URL - PullRequest
118 голосов
/ 15 октября 2008

Я искал простое регулярное выражение для URL, у кого-нибудь есть один удобный инструмент, который хорошо работает? Я не нашел ни одного с классами валидации Zend Framework и видел несколько реализаций.

Ответы [ 20 ]

4 голосов
/ 12 марта 2009

Изменить:
Как указывалось инцидент , этот код устарел с выпуском PHP 5.3.0 (2009-06-30) и должен использоваться соответствующим образом.


Только мои два цента, но я разработал эту функцию и уже давно пользуюсь ею. Он хорошо документирован и разделен, так что вы можете легко его изменить.

// 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;
}
2 голосов
/ 14 декабря 2016

Вдохновленный в этом вопросе .NET StackOverflow и в этой статье, на которую ссылаются из этого вопроса есть этот валидатор URI (URI означает, что он проверяет и URL, и 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." );
}

Я успешно провёл модульное тестирование этой функции внутри объекта 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 )
    {
        // /3907/regex-dlya-proverki-uri
        // 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." );
        }
    }
}

Запуск юнит-тестов

В 46 тестах 65 утверждений. Внимание: есть 2 провайдера данных для действительных и еще 2 для недействительных выражений. Один для URL-адресов, а другой для URN. Если вы используете версию PhpUnit версии 5.5 * или более ранней, то вам нужно объединить двух поставщиков данных в один.

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% покрытия кода.

1 голос
/ 19 февраля 2014

ОК, так что это немного сложнее, чем простое регулярное выражение, но допускает разные типы 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
0 голосов
/ 08 февраля 2017

Вот простой класс для проверки URL с использованием RegEx, а затем перекрестные ссылки на домен по отношению к популярным серверам RBL (списки в реальном времени):

Установка:

require 'URLValidation.php';

Использование:

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

Добавьте URL-адрес в качестве параметра метода domain() и проверьте возврат.

$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, поэтому домен был возвращен как ложный.

0 голосов
/ 14 мая 2015

Для этого есть встроенная функция PHP:

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

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

Возвращает отфильтрованные данные или FALSE в случае сбоя фильтра.

Проверьте это здесь

0 голосов
/ 21 августа 2014

Вот как я это сделал. Но я хочу сказать, что я не настолько уверен в регулярном выражении. Но ты должен работать:)

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

Таким образом, вам не понадобится маркер eval на вашем шаблоне.

Надеюсь, это поможет:)

0 голосов
/ 20 июля 2018
"/(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-] означает любой символ a-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.
    

Примечание: извините за плохой английский. Моя страна не использует это хорошо.

0 голосов
/ 30 мая 2009

Регер Питера не выглядит мне подходящим по многим причинам. Он допускает все виды специальных символов в доменном имени и не проверяет много.

Функция Фрэнки выглядит хорошо для меня, и вы можете создать хорошее регулярное выражение из компонентов, если вам не нужна функция, например:

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

Не проверено, но я думаю, что это должно работать.

Кроме того, ответ Оуэна тоже не выглядит на 100%. Я взял доменную часть регулярного выражения и протестировал ее на инструменте тестирования регулярных выражений http://erik.eae.net/playground/regexp/regexp.html

Я поставил следующую строку:

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

в разделе "регулярное выражение" и следующая строка:

-hello.com

в разделе «Образец текста».

Результат пропущен через минус. Потому что \ S означает любой непробельный символ.

Обратите внимание, что регулярное выражение от Фрэнки обрабатывает минус, потому что у него есть эта часть для первого символа:

[a-z0-9]

Что не позволяет использовать минус или любой другой специальный символ.

0 голосов
/ 31 августа 2018

Для тех, кто разрабатывает с WordPress, просто используйте

esc_url_raw($url) === $url

для проверки URL ( здесь документация WordPress по esc_url_raw). Он обрабатывает URL намного лучше, чем filter_var($url, FILTER_VALIDATE_URL), потому что является Unicode и безопасным для XSS. ( Вот хорошая статья, в которой упоминаются все проблемы с filter_var).

0 голосов
/ 06 августа 2012

Я считаю, что это наиболее полезно для сопоставления URL-адреса ..

^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...