不久前,我研究了使用filter_var()FILTER_VALIDATE_URL 标志使用该函数来验证 URL,最近有人指出该函数不仅自初始发布以来发生了变化,而且可以添加许多标志来改变该函数的方式作品。这是可用的标志。
FILTER_FLAG_SCHEME_REQUIRED要求URL 中的方案(例如,http://、ftp:// 等)。
FILTER_FLAG_HOST_REQUIRED需要 URL 的主机(例如,www.google.com)
FILTER_FLAG_PATH_REQUIRED要求在 URL 的主机后面有一个路径。
FILTER_FLAG_QUERY_REQUIRED要求在 URL 末尾进行查询(例如,?key=value)
这些标志可以添加到正常filter_var()调用中以更改结果的结果。以 FILTER_FLAG_PATH_REQUIRED 标志为例。
filter_var('http://www.bbc.co.uk', FILTER_VALIDATE_URL); // returns http://www.bbc.co.uk (which means it validates) filter_var('http://www.bbc.co.uk', FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED); // returns false
也可以通过将多个标志添加在一起来使用多个标志。例如,如果您想在 URL 中同时要求路径和查询,那么您可以使用以下代码段。
filter_var('http://www.bbc.co.uk', FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED | FILTER_FLAG_QUERY_REQUIRED); // returns false
所以我想我会尝试尽可能完整地测试这些 URL 过滤器,并将结果打印在真值表中。为此,我创建了一堆可以测试的 URL。数组中的每一项都包含一个空数组,每个测试的结果都将放入该数组中。
$urls = array( 'http://www.bbc.co.uk' => array(), 'http://www.hashbangcode.com' => array(), 'http://www.hashbangcode.com/blog' => array(), 'http://www.example.com/index.html#anchor' => array(), 'http://www.example.com/index.html?q=123' => array(), 'example.com' => array(), 'www.example.com' => array(), 'www.example.com/blog' => array(), 'www.example.com/index.html?q=123' => array(), '/index.html?q=123' => array(), 'https://www.example.com/' => array(), 'https://localhost' => array(), 'https://localhost/' => array(), 'https://127.0.0.1/' => array(), 'http://.com' => array(), 'http://...' => array(), 'http://' => array(), 'http://i\'me really trying to break this url!!!"£$"%$&*()' => array() );
然后我创建了一个验证标志列表,包括一个用于测试无标志的 NULL 值和四个标志的不同排列。您可能会问自己,为什么我在这个数组中同时使用字符串和值。原因是标志实际上只是整数常量,所以当我稍后尝试将它们打印出来时,我发现打印的是整数值而不是实际的标志键。因此,为了妥协,我使用标志的字符串表示作为数组键,使用实际标志作为值。
$flags = array( 'Null' => NULL, 'FILTER_FLAG_SCHEME_REQUIRED' => FILTER_FLAG_SCHEME_REQUIRED, 'FILTER_FLAG_HOST_REQUIRED' => FILTER_FLAG_HOST_REQUIRED, 'FILTER_FLAG_PATH_REQUIRED' => FILTER_FLAG_PATH_REQUIRED, 'FILTER_FLAG_QUERY_REQUIRED' => FILTER_FLAG_QUERY_REQUIRED, 'FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED' => FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED, 'FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_PATH_REQUIRED' => FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_PATH_REQUIRED, 'FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_QUERY_REQUIRED' => FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_QUERY_REQUIRED, 'FILTER_FLAG_HOST_REQUIRED | FILTER_FLAG_PATH_REQUIRED' => FILTER_FLAG_HOST_REQUIRED | FILTER_FLAG_PATH_REQUIRED, 'FILTER_FLAG_HOST_REQUIRED | FILTER_FLAG_QUERY_REQUIRED' => FILTER_FLAG_HOST_REQUIRED | FILTER_FLAG_QUERY_REQUIRED, 'FILTER_FLAG_PATH_REQUIRED | FILTER_FLAG_QUERY_REQUIRED' => FILTER_FLAG_PATH_REQUIRED | FILTER_FLAG_QUERY_REQUIRED, 'FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED | FILTER_FLAG_PATH_REQUIRED' => FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED | FILTER_FLAG_PATH_REQUIRED, 'FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_PATH_REQUIRED | FILTER_FLAG_QUERY_REQUIRED' => FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_PATH_REQUIRED | FILTER_FLAG_QUERY_REQUIRED, 'FILTER_FLAG_HOST_REQUIRED | FILTER_FLAG_PATH_REQUIRED | FILTER_FLAG_QUERY_REQUIRED' => FILTER_FLAG_HOST_REQUIRED | FILTER_FLAG_PATH_REQUIRED | FILTER_FLAG_QUERY_REQUIRED, 'FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED | FILTER_FLAG_PATH_REQUIRED | FILTER_FLAG_QUERY_REQUIRED' => FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED | FILTER_FLAG_PATH_REQUIRED | FILTER_FLAG_QUERY_REQUIRED, );
然后将这些阵列拉到一起并按以下方式进行测试。
// 做过滤 foreach ($urls as $url => $data) { foreach ($flags as $textFlag => $flag) { $urls[$url][$textFlag] = (filter_var($url, FILTER_VALIDATE_URL, $flag) === FALSE)? 'FALSE' : 'TRUE'; } }
然后将这些测试的结果打印在两个不同的表中,第一个使用标志作为标题,第二个使用 URL 作为标题。这是打印出表格的代码。
// 以 URL 为行打印表格 $header = '<tr><th>URL</th><th>'; $header .= implode('</th><th>' , array_keys($flags)) . '</th>'; $header .= '</tr>'; $rows = ''; foreach ($urls as $url => $data) { $rows .= '<tr><td>' . $url . '</td>'; foreach ($flags as $textFlag => $flag) { $colour = ($urls[$url][$textFlag] == 'TRUE')? 'green':'red'; $rows .= '<td style="background-color:' . $colour . ';">' . $urls[$url][$textFlag] . '</td>'; } $rows .= '</tr>'; } echo '<table border="1">' . $header . $rows . '</table>'; echo '<br />'; // 打印带有标志作为行的表 $header = '<tr><th>FLAG</th><th>'; $header .= implode('</th><th>' , array_keys($urls)) . '</th>'; $header .= '</tr>'; $rows = ''; foreach ($flags as $textFlag => $flag) { $rows .= '<tr><td>' . $textFlag . '</td>'; foreach ($urls as $url => $data) { $colour = ($urls[$url][$textFlag] == 'TRUE')? 'green':'red'; $rows .= '<td style="background-color:' . $colour . ';">' . $urls[$url][$textFlag] . '</td>'; } $rows .= '</tr>'; } echo '<table border="1">' . $header . $rows . '</table>';
在撰写本文时,所有这些代码都是使用最新版本的 PHP 运行的,即 5.3.3。有很多数据要塞进这个页面,所以我创建了一个结果页面,将完整显示真值表。
我确实发现的一件事是 FILTER_FLAG_SCHEME_REQUIRED 标志似乎没有做任何事情。我认为它可以强制诸如 http:// 之类的东西出现在 URL 的前面,但是由于该filter_var()函数的默认操作不允许该方案被遗漏,所以这个标志基本上是没有意义的。自从我上次查看此验证功能以来,事情已经取得了很大进展,但它仍然没有按预期工作。