我做了一个简单的函数来验证通过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']);
这样做是检查是否
问题是,为什么它不起作用(返回一个空数组)?我检查了每一个检查,它应该工作,但事实并非如此。对不起,如果代码很乱,我还在努力学习。
答案 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请求是同步完成的。如果主持人未能在可接受的时间范围内回复,您的脚本可能会超时 - 或者至少需要多长时间才能完成,具体取决于您检查的网址数量及其背后的服务质量。