【问题标题】:PHP RegEx to allow mailto: http:// and tel: hyperlinksPHP RegEx 允许 mailto: http:// 和 tel: 超链接
【发布时间】:2015-06-23 00:20:27
【问题描述】:

我需要做的是允许文本字段验证并允许 mailto: http:// 或 tel: URL 类型。

我正在使用 PHP 5(和 Laravel 4,但与本文无关)。

我已经在谷歌上搜索了一段时间,但我似乎无法找到一个允许匹配所有三种类型的表达式。我尝试了一些长而复杂的字符串,以及一些真正的短字符串,但它只是返回 false。

这是我的最新消息:

mailto:([^\?]*)|http:([^\?]*)|tel:([^\?]*)

解决方案:

由于我使用的是 Laravel 4,我决定使用 parse_url 函数而不是正则表达式。也就是说,还提供了一些其他出色的解决方案。

我的最终验证器函数:

    Validator::extend('any_url', function($attribute, $value)
    {
        $allowed = ['mailto', 'http', 'https', 'tel'];
        $parsed = parse_url($value);

        return in_array($parsed['scheme'], $allowed);
    });

【问题讨论】:

  • 捕捉零件? (mailto:([^\?]*))|(http:([^\?]*))|(tel:([^\?]*))
  • 如果您只需要验证,您可以使用filter_varFILTER_VALIDATE_URL 作为过滤器。你可以在这里查看一些测试:php.net/manual/en/filter.filters.validate.php#110411
  • ^^ FILTER_VALIDATE_URL 几乎是答案,但它不支持 tel: protocol

标签: php regex laravel


【解决方案1】:

你可能需要这个:

/^((?:tel|https?|mailto):.*?)$/

示例:

 $strings  = array("http://www.me.com", "mailto:hey@there.nyc", "tel:951261412", "hyyy://www.me.com");

foreach($strings as $string){

if (preg_match('/^((?:tel|https?|mailto):.*?)$/im', $string)) {
    echo $string ."\n";
}else{
echo "No Match for : $string \n";
}
}

DEMO PHP
DEMO REGEX

解释:

^((?:tel|https?|mailto):.*?)$
-----------------------------

Assert position at the beginning of a line (at beginning of the string or after a line break character) (line feed) «^»
Match the regex below and capture its match into backreference number 1 «((?:tel|https?|mailto):.*?)»
   Match the regular expression below «(?:tel|https?|mailto)»
      Match this alternative (attempting the next alternative only if this one fails) «tel»
         Match the character string “tel” literally (case insensitive) «tel»
      Or match this alternative (attempting the next alternative only if this one fails) «https?»
         Match the character string “http” literally (case insensitive) «http»
         Match the character “s” literally (case insensitive) «s?»
            Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
      Or match this alternative (the entire group fails if this one fails to match) «mailto»
         Match the character string “mailto” literally (case insensitive) «mailto»
   Match the character “:” literally «:»
   Match any single character that is NOT a line break character (line feed) «.*?»
      Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
Assert position at the end of a line (at the end of the string or before a line break character) (line feed) «$»

【讨论】:

    【解决方案2】:

    试试这个:

    ((mailto:\w+)|(tel:\w+)|(http://\w+)).+
    

    http://regexr.com/3ar2c

    【讨论】:

      【解决方案3】:

      您可以使用parse_url,这将为您提供scheme。然后检查是否在['mailto', 'http', 'https','tel']

      【讨论】:

      • 啊,这是个好主意。实际上,在这种情况下,我使用的是 Laravel 验证器,它需要字符串...
      • 我最终决定使用它,因为它是一种更易于阅读和扩展的解决方案,而且它与 Laravel 配合得很好。我在上面发布了我的最终代码
      • 在您的最终答案中,您没有检查字符串是否没有任何协议,因此不会设置 $parsed['scheme']!isset($parsed['scheme']).
      【解决方案4】:

      您需要将整个正则表达式放在一个捕获分组中,还需要在http: 之后使用//

      mailto:([^\?]*)|(http://([^\?]*))|(tel:([^\?]*))
      

      因为在您的正则表达式中,点子的工作方式不同:

      mailto:     #first
      ([^\?]*)|http: #second
      ([^\?]*)|tel:  #third
      ([^\?]*)       #fourth
      

      【讨论】:

        猜你喜欢
        • 2019-10-18
        • 1970-01-01
        • 2020-02-04
        • 2015-07-09
        • 1970-01-01
        • 1970-01-01
        • 2018-10-06
        • 2012-06-18
        • 1970-01-01
        相关资源
        最近更新 更多