PHP filter_var() 函数
完整的 PHP Filter 参考手册
定义和用法
filter_var() 函数通过指定的过滤器过滤一个变量。
如果成功,则返回被过滤的数据。如果失败,则返回 FALSE。
语法
filter_var(variable, filter, options)
参数 | 描述 |
---|
variable | 必需。规定要过滤的变量。 |
filter | 可选。规定要使用的过滤器的 ID。默认是 FILTER_SANITIZE_STRING。参见 完整的 PHP Filter 参考手册,查看可能的过滤器。 过滤器 ID 可以是 ID 名称(比如 FILTER_VALIDATE_EMAIL)或 ID 号(比如 274)。 |
options | 可选。规定一个包含标志/选项的关联数组或者一个单一的标志/选项。检查每个过滤器可能的标志和选项。 |
实例
<?php
if(!filter_var("
someone@example....com", FILTER_VALIDATE_EMAIL))
{
echo("E-mail is not valid");
}
else
{
echo("E-mail is valid");
}
?>
代码的输出如下所示:
完整的 PHP Filter 参考手册
来自 https://www.runoob.com/php/func-filter-var.html
filter_var
(PHP 5 >= 5.2.0, PHP 7, PHP 8)
filter_var — 使用特定的过滤器过滤一个变量
说明 ¶
filter_var(
mixed $value
,
int $filter
= FILTER_DEFAULT
,
array|int $options
= 0):
mixed 参数 ¶
value
要过滤的内容。注意:标量值在过滤前,会被转换成字符串。
filter
The ID of the filter to apply. The Types of filters manual page lists the available filters.
If omitted, FILTER_DEFAULT
will be used, which is equivalent to FILTER_UNSAFE_RAW
. This will result in no filtering taking place by default.
options
一个选项的关联数组,或者按位区分的标示。如果过滤器接受选项,可以通过数组的 "flags" 下标去提供这些标示。 对于回调型的过滤器,应该传入 callable。 这个回调函数必须接受一个参数(即待过滤的值),并且返回一个在过滤/净化后的值。
<?php
// 对于接受选项的过滤器,请使用此格式
$options = array(
'options' => array(
'default' => 3, // 过滤器失败时返回的值
// 可以继续写过滤器接收其它选项
'min_range' => 0
),
'flags' => FILTER_FLAG_ALLOW_OCTAL,
);
$var = filter_var('0755', FILTER_VALIDATE_INT, $options);
// 对于仅接受标志的过滤器,您可以直接将其传递
$var = filter_var('oops', FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
// 对于仅接受标志的过滤器,您还可以将其作为数组传递
$var = filter_var('oops', FILTER_VALIDATE_BOOLEAN,
array('flags' => FILTER_NULL_ON_FAILURE));
// 回调类型过滤器
function foo($value)
{
// 预期值: Surname, GivenNames
if (strpos($value, ", ") === false) return false;
list($surname, $givennames) = explode(", ", $value, 2);
$empty = (empty($surname) || empty($givennames));
$notstrings = (!is_string($surname) || !is_string($givennames));
if ($empty || $notstrings) {
return false;
} else {
return $value;
}
}
$var = filter_var('Doe, Jane Sue', FILTER_CALLBACK, array('options' => 'foo'));
?>
返回值 ¶
返回过滤后的数据,如果过滤失败则返回 false
。
范例 ¶
示例 #1 一个 filter_var() 的示例
<?php
var_dump(filter_var('bob@example.com', FILTER_VALIDATE_EMAIL));
var_dump(filter_var('http://example.com', FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED));
?>
string(15) "bob@example.com"
bool(false)
cabrinosimone at gmail dot com ¶9 years ago
Pay attention that the function will not validate "not latin" domains.
if (filter_var('уникум@из.рф', FILTER_VALIDATE_EMAIL)) {
echo 'VALID';
} else {
echo 'NOT VALID';
}
gt at kani dot hu ¶9 years ago
I found some addresses that FILTER_VALIDATE_EMAIL rejects, but RFC5321 permits:
<?php
foreach (array(
'localpart.ending.with.dot.@example.com',
'(comment)localpart@example.com',
'"this is v@lid!"@example.com',
'"much.more unusual"@example.com',
'postbox@com',
'admin@mailserver1',
'"()<>[]:,;@\\"\\\\!#$%&\'*+-/=?^_`{}| ~.a"@example.org',
'" "@example.org',
) as $address) {
echo "<p>$address is <b>".(filter_var($address, FILTER_VALIDATE_EMAIL) ? '' : 'not')." valid</b></p>";
}
?>
Results:
localpart.ending.with.dot.@example.com is not valid
(comment)localpart@example.com is not valid
"this is v@lid!"@example.com is not valid
"much.more unusual"@example.com is not valid
postbox@com is not valid
admin@mailserver1 is not valid
"()<>[]:,;@\"\\!#$%&'*+-/=?^_`{}| ~.a"@example.org is not valid
" "@example.org is not valid
The documentation does not saying that FILTER_VALIDATE_EMAIL should pass the RFC5321, however you can meet with these examples (especially with the first one). So this is a note, not a bug report.
divinity76 at gmail dot com ¶5 years ago
note that FILTER_VALIDATE_BOOLEAN tries to be smart, recognizing words like Yes, No, Off, On, both string and native types of true and false, and is not case-sensitive when validating strings.
<?php
$vals=array('on','On','ON','off','Off','OFF','yes','Yes','YES',
'no','No','NO',0,1,'0','1','true',
'True','TRUE','false','False','FALSE',true,false,'foo','bar');
foreach($vals as $val){
echo var_export($val,true).': '; var_dump(filter_var($val,FILTER_VALIDATE_BOOLEAN,FILTER_NULL_ON_FAILURE));
}
?>
outputs:
'on': bool(true)
'On': bool(true)
'ON': bool(true)
'off': bool(false)
'Off': bool(false)
'OFF': bool(false)
'yes': bool(true)
'Yes': bool(true)
'YES': bool(true)
'no': bool(false)
'No': bool(false)
'NO': bool(false)
0: bool(false)
1: bool(true)
'0': bool(false)
'1': bool(true)
'true': bool(true)
'True': bool(true)
'TRUE': bool(true)
'false': bool(false)
'False': bool(false)
'FALSE': bool(false)
true: bool(true)
false: bool(false)
'foo': NULL
'bar': NULL
rschuetz at hmcw dot com ¶1 year ago
I cannot confirm what yactouat said. As of PHP 7.3, 0 will not be filtered out with FILTER_VALIDATE_INT. It correctly returns 0, not false. Of course you have to check the return value with an identity operator. Otherwise you cannot distinguish between 0 and false.
Steve ¶4 years ago
The note from "hek" about HTML5 having patterns thus alleviating the need to filter in PHP is completely wrong: You still must filter input on the server side. The HTML5 form inputs are client-side, meaning they are completely under the user's control. Only when you receive the data in PHP is it server-side and under your control. Once the data is under your control, then you must filter/sanitize it properly.
This is true regardless of server-side language. I would encourage the moderators to remove the note from "hek" because it will mislead people with horrible consequences.
Steve
Robert Vlach ¶2 years ago
I won't recommend using this function to validate email addresses on a normal website. The problem is that in accordance with RFC 3696 (Application Techniques for Checking and Transformation of Names) the following email addresses would be considered as valid:
customer/department=shipping@example.com
$A12345@example.com
!def!xyz%abc@example.com
_somename@example.com
"Abc@def"@example.com
Hardly something I would accept in a live web app in 2020 :-/
Anonymous ¶7 years ago
FILTER_VALIDATE_URL allows:
filter_var('javascript://comment%0Aalert(1)', FILTER_VALIDATE_URL);
Where the %0A (URL encoded newline), in certain contexts, will split the comment from the JS code.
This can result in an XSS vulnerability.
marcus at synchromedia dot co dot uk ¶10 years ago
It's very likely that you actually want to detect all reserved ranges, not just private IPs, and there's another constant for them that should be bitwise-OR'd with it.
<?php
function is_private_ip($ip) {
return !filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE);
}
?>
jon dot bertsch at ucop dot edu ¶13 years ago
Here's an actual example of the filter syntax with a flag since there doesn't appear to be a one liner for this anywhere:
'hours' => array('filter'=>FILTER_SANITIZE_NUMBER_FLOAT, 'flags' => FILTER_FLAG_ALLOW_FRACTION, 'options'=> '.')
yactouat at hotmail dot com ¶3 years ago
While getting familiar with filter_var( $var, FILTER_VALIDATE_INT ), I found interesting that 0 will be filtered out and therefore wont be considered as an int. Hope that helps someone not to be stuck ;)
N.B.: if you need to accept 0's, you could use is_int()
dale dot liszka at gmail dot com ¶14 years ago
Using the FILTER_CALLBACK requires an array to be passed as the options:
<?php
function toDash($x){
return str_replace("_","-",$x);
}
echo filter_var("asdf_123",FILTER_CALLBACK,array("options"=>"toDash"));
?>
dale dot liszka at gmail dot com ¶14 years ago
Here is how to use multiple flags (for those who learn better by example, like me):
<?php
echo "|asdf".chr(9).chr(128)."_123|";
echo "\n";
echo filter_var("|asdf".chr(9).chr(128)."_123\n|" ,FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH);
?>
joe at bloe dot com ¶8 years ago
"(comment)localpart@example.com"
is an invalid E-Mail address per RFC5322 (Appendix A.6.3):
"Also, the comments and white space throughout addresses, dates, and message identifiers are all part of the obsolete syntax."
php at maisqi dot com ¶11 years ago
FILTER_VALIDATE_URL does not support internationalized domain name (IDN). Valid or not, no domain name with Unicode chars on it will pass validation.
We can circumvent this with a home grown solutions, but C code is C code, so I've gone for the code bellow, which builds on filter_var().
<?php
$res = filter_var ($uri, FILTER_VALIDATE_URL);
if ($res) return $res;
$l = mb_strlen ($uri);
if ($l !== strlen ($uri)) {
$s = str_repeat (' ', $l);
for ($i = 0; $i < $l; ++$i) {
$ch = mb_substr ($uri, $i, 1);
$s [$i] = strlen ($ch) > 1 ? 'X' : $ch;
}
$res = filter_var ($s, FILTER_VALIDATE_URL);
if ($res) { $uri = $res; return 1; }
}
?>
The logic is simple. A non-ascii char is more than one byte long. We replace every one of those chars by "X" and check again.
An alternative will be to punycode the URI before calling filter_var(), but PHP lacks native support for punycode. I think my approach is effective. Please e-mail me if you think otherwise or see room for improvement.
dan at spiral8 dot net ¶7 years ago
Here's a simple test using filter_var with FILTER_VALIDATE_URL.
(If you're using file_get_contents after this you will run into a problem, I was using: PHP 5.5.12 (cli))
<?php
$url = 'a://google.com';
$result = filter_var($url, FILTER_VALIDATE_URL);
if($result){
echo 'Valid URL'.PHP_EOL;
}
var_dump($result);
?>
The result is:
Valid URL
string(14) "a://google.com"
yoanlin93 at gmail dot com ¶7 years ago
Some boolean conversions:
<?php
var_dump(filter_var('oops', FILTER_VALIDATE_BOOLEAN, array('flags' => FILTER_NULL_ON_FAILURE)));
var_dump(filter_var('false', FILTER_VALIDATE_BOOLEAN, array('flags' => FILTER_NULL_ON_FAILURE)));
var_dump(filter_var('true', FILTER_VALIDATE_BOOLEAN, array('flags' => FILTER_NULL_ON_FAILURE)));
var_dump(filter_var(0, FILTER_VALIDATE_BOOLEAN, array('flags' => FILTER_NULL_ON_FAILURE)));
var_dump(filter_var(1, FILTER_VALIDATE_BOOLEAN, array('flags' => FILTER_NULL_ON_FAILURE)));
var_dump(filter_var('TRUE', FILTER_VALIDATE_BOOLEAN, array('flags' => FILTER_NULL_ON_FAILURE)));
var_dump(filter_var('', FILTER_VALIDATE_BOOLEAN, array('flags' => FILTER_NULL_ON_FAILURE)));
var_dump(filter_var('FALSE', FILTER_VALIDATE_BOOLEAN, array('flags' => FILTER_NULL_ON_FAILURE)));
crisp at tweakers dot net ¶4 years ago
Note that only using FILTER_VALIDATE_URL to validate url's input may result in XSS:
$url = 'javascript://%0Aalert(document.cookie)';
if (filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED)) {
echo '<a href="' . $url . '">click</a>';
}
You should at least additionally check the actually used scheme.
alex4home at gmail dot com ¶9 years ago
Keep in mind that FILTER_VALIDATE_EMAIL will validate the email address according to standards.
However, giving the fact that organizations are free to restrict the forms of their own email addresses, using ONLY this filter can you a lot of bounces.
gmail, yahoo, hotmail, aol have special rules
For example :
<?php
$email_a = '0hot\'mail_check@hotmail.com';
if (filter_var($email_a, FILTER_VALIDATE_EMAIL)) {
echo "This (email_a) email address is considered valid.";
}
?>
Ant ¶7 years ago
Note: filter_var with filter=FILTER_VALIDATE_URL used parse_url function
dyer85 at gmail dot com ¶14 years ago
Note that when using FILTER_VALIDATE_INT along with the FILTER_FLAG_ALLOW_HEX flag, the string "2f", for example, is not validated successfully, because you must use the "0x" prefix, otherwise, it treats the data as base 10.
The range options are also smart enough to recognize when the boundaries are exceeded in different bases.
Here's an example:
<?php
$foo = '256';
$bar = '0x100';
var_dump(validate_int($foo)); var_dump(validate_int($bar)); function validate_int($input)
{
return filter_var(
$input,
FILTER_VALIDATE_INT,
array(
'flags' => FILTER_FLAG_ALLOW_HEX,
'options' => array('min_range' => 1, 'max_range' => 0xff)
)
);
}
?>
drew_mirage at hotmail dot com ¶9 years ago
One key thing to remember about filtering integers is that the value for the option max_range must be less than or equal to the value of PHP_INT_MAX.
filter_var($someVariable, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => SOME_VALUE_GREATER_THAN_PHP_INT_MAX)));
This will fail even if $someVariable is a valid integer in the expected range.
This can show up when you are attempting to validate a potential key for an unsigned MySQL INT type (whose maximum value is 4294967295) on a 32-bit system, where the value of PHP_INT_MAX is 2147483647.
Martin L ¶10 years ago
FILTER_SANITIZE_EMAIL header injection test.
<?php
$InjString = "\r\n|\n|%0A|%0D|bcc:|to:|cc:|Content-Type:|Mime-Type:|";
echo filter_var($InjString, FILTER_SANITIZE_EMAIL);
?>
||%0A|%0D|bcc|to|cc|Content-Type|Mime-Type|
alice at deviant dot email ¶6 years ago
Many people, myself included, have found that the FILTER_VALIDATE_EMAIL does not actually properly work.
Below is a wrapper that I believe validates every legal routable address.
<?php
function check_username($uname) {
if (iconv('UTF-8', 'UTF-8', $input) != $input) {
return FALSE;
}
$uname = preg_replace('/[\x{007F}-\x{FFFF}]/u', 'U', $uname);
$s[] = '/^\([^\)]*\)/'; $s[] = '/\([^\)]*\)$/';
$uname = preg_replace($s, '', $uname);
if(strlen(trim($uname)) == 0) {
return FALSE;
}
if(substr_count($uname, '..') > 0) {
return FALSE;
}
$s[] = '/[\\\][\\\]/';
$s[] = '/\\\"/';
$uname = preg_replace($s, 'A', $uname);
if(preg_match('/[^.]+"[^.]+/', $uname)) {
return FALSE;
}
$uname = preg_replace_callback('/"(.*)"/', function ($m) {
$s[]="/[ \(\),\:;<>@\[\] ]/";
return preg_replace($s,'Q',$m[1]);
}, $uname);
return filter_var($uname . '@example.org', FILTER_VALIDATE_EMAIL);
}
function check_email($email, $dns_check=true) {
$array = explode('@', $email);
if(count($array) < 2) {
return FALSE;
}
$domain = end($array);
array_pop($array);
if(function_exists('idn_to_ascii')) {
$domain = idn_to_ascii($domain);
}
$ipcheck = preg_replace(array('/^\[ipv6\:/i', '/^\[/', '/\]$/'), '', $domain);
if(filter_var($ipcheck, FILTER_VALIDATE_IP)) {
if(! filter_var($ipcheck, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
return FALSE;
}
} else {
if(! filter_var('user@a.' . $domain, FILTER_VALIDATE_EMAIL)) {
return FALSE;
}
if($dns_check) {
if(! dns_get_record($domain)) {
return FALSE;
}
}
}
return check_username(implode('@', $array));
}
?>
It evaluates the address in two parts, first evaluating the host and if that legal it then evaluates the user name.
If there is a DNS problem *and* the default $dns_check value of true is used, valid will fail. If it is an international domain name, you have to have the php-intl package installed.
Enjoy.
Tom ¶9 years ago
It is important to note that though the data type of the first parameter of the function is stated as "mixed", this is only one half of the truth.
While it accepts any data type, the first parameter will always be cast to string before being validated or sanitized.
It seems that this function was designed strictly to be used on user input strings. For example: from an online-form. When using it for anything other than that, you may see issues. So read the documentation very carefully!
Especially note that there is an (to date) unresolved issue (#49510) concerning the Boolean filter while using the FILTER_NULL_ON_FAILURE flag. Note that both (string) FALSE and FALSE are not recognized as boolean values and will return NULL (not FALSE as you might expect).
I thus personally suggest that (to date) the best way to take the filter_var()-functions beyond their original purpose (and allow future extension and customization) is to wrap them in your own classes. This will allow you to work-around unexpected behavior on non-string input and add your custom checks, or back-port filters or sanitizers that may be added in later versions of PHP.
(Especially since PHP currently still lacks filters and sanitizers for some of the more exotic HTML5 input types, like "color". Thus there actually is a chance that we may see a need for custom filters or backports at some point in the future.)
joelhy ¶11 years ago
For those looking for private ip checking, there it is:
<?php
function is_private_ip($ip)
{
return !filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE);
}
?>
drtebi at yahoo ¶13 years ago
Notice that filter_var with FILTER_VALIDATE_EMAIL does not work if you are trying to get a String from an XML document e.g. via xpath.
I often use XML files as configuration files and use a function that returns a string from the config file via xpath. While this worked fine before 5.2.11, it doesn't anymore (and shouldn't, since it's an XML Element, not a String).
To overcome this problem, $variable can be type-casted:
<?php
$variable = fancyXmlGetFunction('from');
filter_var((String) $variable, FILTER_VALIDATE_EMAIL);
?>
来自 https://www.php.net/manual/zh/function.filter-var.php