验证网址并删除重复项

时间:2012-07-06 10:45:09

标签: php validation

我做了一个简单的函数来验证通过textarea提交的URL(每行1个链接):

function validate_urls($value)
{
    //final array of links
    $links = array();

    $value = array_map(function($a) use (&$links){
        $a = trim($a);
        if(strlen($a) !== 0 and (strpos($a, 'http') !== 0 or strpos($a, 'https') !== 0)){
            $a = 'http://'.$a;
        }
        $url = parse_url($a,PHP_URL_HOST);
        if($url != null and !in_array($a, $links) and filter_var($a, FILTER_VALIDATE_URL) !== false and checkdnsrr($a)){
            $links[] = $a;
        }
        return false;
    }, explode("\n",$value));
    return $links;
}

var_dump(validate_urls($_POST['links']);

这样做是检查是否

  • 网址有效
  • 网址有效
  • 网址不重复

问题是,为什么它不起作用(返回一个空数组)?我检查了每一个检查,它应该工作,但事实并非如此。对不起,如果代码很乱,我还在努力学习。

1 个答案:

答案 0 :(得分:1)

if(strlen($a) !== 0 and (strpos($a, 'http') !== 0 or strpos($a, 'https') !== 0)){

A and B or C不会转换为(A and B) or (A and C),因为AND的优先级高于OR。因此,您希望将其更改为A and (B or C)


FILTER_VALIDATE_URL状态的docs»请注意,该函数只能找到有效的ASCII URL;«。所以这是一个相当严格的选择。它遵守RFC 2396中提供的网址规范,该网址已被RFC 3986取代。

如果没有更彻底地研究过滤器,这两条信息就足以(对我而言)将该过滤器标记为完全没用。


checkdnsrr($a)

正在测试整个网址而不仅仅是主机。即使你要检查主机,你也要寻找MX记录(即如果所述主机可以通过邮件访问)。 A将检查该主机是否具有IP集,CNAME将检查该主机是否是另一个DNS记录的别名,....您可能正在寻找NS来检查该主机是否有任何DNS记录。

因此,如果您将支票更改为checkdnsrr($url, "NS"),那么您将验证该URL的主机组件是否实际为DNS所知。您没有检查该主机是否实际上正在侦听指定的端口。而且你不会检查给定的资源(例如/foo/bar.html)是否存在。


如果您想确保网址确实指向有用的内容,则必须发出HEAD请求并检查响应。您可以使用curl轻松完成此操作。如果curl不可用,您可以使用fsockopen()自己实现一个简单的HTTP客户端 - 缺点是无法说HTTP(HTTP通过SSL)并且必须自己实现重定向跟随和类似的东西。简而言之:你不想走那条路。

尽管如此,未来还存在性能问题。 HTTP请求是同步完成的。如果主持人未能在可接受的时间范围内回复,您的脚本可能会超时 - 或者至少需要多长时间才能完成,具体取决于您检查的网址数量及其背后的服务质量。