php 如何避免isset()和empty()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1960509/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to avoid isset() and empty()
提问by Pekka
I have several older applications that throw a lot of "xyz is undefined" and "undefined offset" messages when running on the E_NOTICE error level, because the existence of variables is not explicitly checked using isset()and consorts.
我有几个较旧的应用程序在 E_NOTICE 错误级别上运行时会抛出大量“xyz 未定义”和“未定义偏移”消息,因为未使用isset()和 consorts显式检查变量的存在。
I am considering working through them to make them E_NOTICE compatible, as notices about missing variables or offsets can be lifesavers, there may be some minor performance improvements to be gained, and it's overall the cleaner way.
我正在考虑通过它们使它们与 E_NOTICE 兼容,因为有关缺少变量或偏移量的通知可以挽救生命,可能会获得一些小的性能改进,并且总体上是更清洁的方式。
However, I don't like what inflicting hundreds of isset()empty()and array_key_exists()s does to my code. It gets bloated, becomes less readable, without gaining anything in terms of value or meaning.
但是,我不喜欢对我的代码造成数百个isset()empty()和array_key_exists()s 的影响。它变得臃肿,变得不那么可读,没有获得任何价值或意义。
How can I structure my code without an excess of variable checks, while also being E_NOTICE compatible?
如何在不进行过多变量检查的情况下构建我的代码,同时与 E_NOTICE 兼容?
回答by deceze
For those interested, I have expanded this topic into a small article, which provides the below information in a somewhat better structured form: The Definitive Guide To PHP's isset And empty
对于那些感兴趣的人,我已将此主题扩展为一篇小文章,该文章以更好的结构形式提供了以下信息:PHP 的 isset 和空的权威指南
IMHO you should think about not just making the app "E_NOTICE compatible", but restructuring the whole thing. Having hundredsof points in your code that regularly try to use non-existent variables sounds like a rather badly structured program. Trying to access non-existent variables should never ever happen, other languages balk at this at compile time. The fact that PHP allows you to do it doesn't mean you should.
恕我直言,您不仅应该考虑使应用程序“兼容 E_NOTICE”,还应该考虑重构整个过程。在您的代码中有数百个经常尝试使用不存在的变量的点听起来像是一个结构相当糟糕的程序。尝试访问不存在的变量永远不应该发生,其他语言在编译时对此犹豫不决。PHP 允许您这样做的事实并不意味着您应该这样做。
These warnings are there to helpyou, not to annoy you. If you get a warning "You're trying to work with something that doesn't exist!", your reaction should be "Oops, my bad, let me fix that ASAP."How else are you going to tell the difference between "variables that work just fine undefined"and honestly wrong code that may lead to serious errors? This is also the reason why you always, always, develop with error reporting turned to 11and keep plugging away at your code until not a single NOTICEis issued. Turning error reporting off is for production environments only, to avoid information leakage and provide a better user experience even in the face of buggy code.
这些警告是为了帮助您,而不是为了惹恼您。如果您收到警告“您正在尝试使用不存在的东西!” ,你的反应应该是“糟糕,我的错,让我尽快解决这个问题。” 您还能如何区分“未定义的工作正常的变量”和可能导致严重错误的老实说错误的代码之间的区别?这也是为什么你总是,总是,在错误报告变成 11 的情况下进行开发,并不断地插入你的代码直到没有一个NOTICE发出。关闭错误报告仅适用于生产环境,以避免信息泄漏并提供更好的用户体验,即使面对有错误的代码。
To elaborate:
详细说明:
You will always need issetor emptysomewhere in your code, the only way to reduce their occurrence is to initialize your variables properly. Depending on the situation there are different ways to do that:
你总是需要isset或empty在你的代码中的某个地方,减少它们出现的唯一方法是正确初始化你的变量。根据情况有不同的方法来做到这一点:
Function arguments:
函数参数:
function foo ($bar, $baz = null) { ... }
There's no need to check whether $baror $bazare set inside the function because you just set them, all you need to worry about is if their value evaluates to trueor false(or whatever else).
无需检查$bar或是否$baz在函数内部设置,因为您只是设置了它们,您只需要担心它们的值是否为trueor false(或其他任何值)。
Regular variables anywhere:
任何地方的常规变量:
$foo = null;
$bar = $baz = 'default value';
Initialize your variables at the top of a block of code in which you're going to use them. This solves the !issetproblem, ensures that your variables always have a known default value, gives the reader an idea of what the following code will work on and thereby also serves as a sort of self-documentation.
在将要使用它们的代码块的顶部初始化变量。这解决了这个!isset问题,确保你的变量总是有一个已知的默认值,让读者了解下面的代码将做什么,从而也可以作为一种自我文档。
Arrays:
数组:
$defaults = array('foo' => false, 'bar' => true, 'baz' => 'default value');
$values = array_merge($defaults, $incoming_array);
The same thing as above, you're initializing the array with default values and overwrite them with actual values.
与上述相同,您使用默认值初始化数组并用实际值覆盖它们。
In the remaining cases, let's say a template where you're outputting values that may or may not be set by a controller, you'll just have to check:
在其余情况下,假设您输出的值可能由控制器设置,也可能不由控制器设置,您只需要检查:
<table>
<?php if (!empty($foo) && is_array($foo)) : ?>
<?php foreach ($foo as $bar) : ?>
<tr>...</tr>
<?php endforeach; ?>
<?php else : ?>
<tr><td>No Foo!</td></tr>
<?php endif; ?>
</table>
If you find yourself regularly using array_key_exists, you should evaluate what you're using it for. The only time it makes a difference is here:
如果您发现自己经常使用array_key_exists,您应该评估您使用它的目的。唯一不同的地方是:
$array = array('key' => null);
isset($array['key']); // false
array_key_exists('key', $array); // true
As stated above though, if you're properly initializing your variables, you don't need to check if the key exists or not, because you know it does. If you're getting the array from an external source, the value will most likely not be nullbut '', 0, '0', falseor something like it, i.e. a value you can evaluate with issetor empty, depending on your intent. If you regularly set an array key to nulland want it to mean anything but false, i.e. if in the above example the differing results of issetand array_key_existsmake a difference to your program logic, you should ask yourself why. The mere existence of a variable shouldn't be important, only its value should be of consequence. If the key is a true/falseflag, then use trueor false, not null. The only exception to this would be 3rd party libraries that want nullto mean something, but since nullis so hard to detect in PHP I have yet to find any library that does this.
如上所述,如果您正确初始化了变量,则无需检查密钥是否存在,因为您知道它确实存在。如果您收到来自外部源的阵列,该值将最有可能不是null,但是'',0,'0',false或类似的东西,也就是一个值,你可以用评估isset或者empty,这取决于你的意图。如果您经常将数组键设置为null并希望它表示除 之外的任何内容false,即如果在上面的示例中 的不同结果isset和array_key_exists对您的程序逻辑产生影响,您应该问自己为什么。变量的存在不重要,重要的是它的值。如果键是true/false标志,则使用true或者false,不是null。唯一的例外是想要有意义的 3rd 方库null,但由于null在 PHP 中很难检测到,我还没有找到任何可以做到这一点的库。
回答by BalusC
Just write a function for that. Something like:
只需为此编写一个函数。就像是:
function get_string($array, $index, $default = null) {
if (isset($array[$index]) && strlen($value = trim($array[$index])) > 0) {
return get_magic_quotes_gpc() ? stripslashes($value) : $value;
} else {
return $default;
}
}
which you can use as
您可以将其用作
$username = get_string($_POST, 'username');
Do the same for trivial stuff like get_number(), get_boolean(), get_array()and so on.
用同样的方法一样琐碎的东西get_number(),get_boolean(),get_array()等等。
回答by Jamol
I believe one of the best ways of coping with this problem is by accessing values of GET and POST (COOKIE, SESSION, etc.) arrays through a class.
我相信解决这个问题的最好方法之一是通过类访问 GET 和 POST(COOKIE、SESSION 等)数组的值。
Create a class for each of those arrays and declare __getand __setmethods (overloading). __getaccepts one argument which will be the name of a value. This method should check this value in the corresponding global array, either using isset()or empty()and return the value if it exists or null(or some other default value) otherwise.
为每个数组创建一个类并声明__get和__set方法(重载)。__get接受一个参数,它将是一个值的名称。此方法应检查相应全局数组中的此值,使用isset()或empty()并返回该值(如果存在)或null(或其他一些默认值)否则。
After that you can confidently access array values in this manner: $POST->usernameand do any validation if needed without using any isset()s or empty()s. If usernamedoes not exist in the corresponding global array then nullwill be returned, so no warnings or notices will be generated.
之后,您可以放心地以这种方式访问数组值:$POST->username并在需要时进行任何验证,而无需使用任何isset()s 或empty()s。如果username不存在于相应的全局数组中,null则将返回,因此不会生成警告或通知。
回答by Alix Axel
I don't mind using the array_key_exists()function. In fact, I prefer using this specific functionrather than relying on hackfunctions which may change their behavior in the future like (strikedthrough to avoid susceptibilities).emptyand isset
我不介意使用该array_key_exists()功能。事实上,我更喜欢使用这个特定的函数,而不是依赖hack函数,这些函数在未来可能会改变它们的行为,比如(删除线以避免敏感性)。empty和isset
I do however, use a simple function that comes handy in this, and some other situations in dealing with array indexes:
但是,我确实使用了一个很方便的简单函数,以及处理数组索引的其他一些情况:
function Value($array, $key, $default = false)
{
if (is_array($array) === true)
{
settype($key, 'array');
foreach ($key as $value)
{
if (array_key_exists($value, $array) === false)
{
return $default;
}
$array = $array[$value];
}
return $array;
}
return $default;
}
Let's say you've the following arrays:
假设您有以下数组:
$arr1 = array
(
'xyz' => 'value'
);
$arr2 = array
(
'x' => array
(
'y' => array
(
'z' => 'value',
),
),
);
How do you get the "value" out of the arrays? Simple:
你如何从数组中获取“值”?简单的:
Value($arr1, 'xyz', 'returns this if the index does not exist');
Value($arr2, array('x', 'y', 'z'), 'returns this if the index does not exist');
We already have uni and multi-dimensional arrays covered, what else can we possibly do?
我们已经涵盖了单维和多维数组,我们还能做什么?
Take the following piece of code for instance:
以下面的一段代码为例:
$url = 'https://stackoverflow.com/questions/1960509';
$domain = parse_url($url);
if (is_array($domain) === true)
{
if (array_key_exists('host', $domain) === true)
{
$domain = $domain['host'];
}
else
{
$domain = 'N/A';
}
}
else
{
$domain = 'N/A';
}
Pretty boring isn't it? Here is another approach using the Value()function:
很无聊是不是?这是使用该Value()函数的另一种方法:
$url = 'https://stackoverflow.com/questions/1960509';
$domain = Value(parse_url($url), 'host', 'N/A');
As an additional example, take the RealIP()functionfor a test:
作为一个额外的例子,拿这个RealIP()函数进行测试:
$ip = Value($_SERVER, 'HTTP_CLIENT_IP', Value($_SERVER, 'HTTP_X_FORWARDED_FOR', Value($_SERVER, 'REMOTE_ADDR')));
Neat, huh? ;)
整洁吧?;)
回答by Jan Turoň
I use these functions
我使用这些功能
function load(&$var) { return isset($var) ? $var : null; }
function POST($var) { return isset($_POST[$var]) ? $_POST[$var] : null; }
Examples
例子
$y = load($x); // null, no notice
// this attitude is both readable and comfortable
if($login=POST("login") and $pass=POST("pass")) { // really =, not ==
// executes only if both login and pass were in POST
// stored in $login and $pass variables
$authorized = $login=="root" && md5($pass)=="f65b2a087755c68586568531ad8288b4";
}
回答by vava
I'm here with you. But PHP designers has made a lot more worse mistakes than that. Short of defining a custom function for any value reading, there isn't any way around it.
我在这里陪着你。但是 PHP 设计者犯了比这更糟糕的错误。没有为任何值读取定义自定义函数,没有任何方法可以解决它。
回答by Alexandre Thebaldi
Welcome to null coalescing operator(PHP >= 7.0.1):
欢迎使用空合并运算符(PHP >= 7.0.1):
$field = $_GET['field'] ?? null;
PHP says:
PHP 说:
The null coalescing operator (??) has been added as syntactic sugar for the common case of needing to use a ternary in conjunction with isset(). It returns its first operand if it exists and is not NULL; otherwise it returns its second operand.
空合并运算符 (??) 已被添加为语法糖,用于需要将三元与 isset() 结合使用的常见情况。如果存在且不为 NULL,则返回其第一个操作数;否则它返回它的第二个操作数。
回答by dragonfire
Make a function which returns falseif not set, and, if specified, falseif empty. If valid it returns the variable. You can add more options as seen in the code below:
创建一个函数,false如果未设置则返回,如果指定false则返回空。如果有效,则返回变量。您可以添加更多选项,如下面的代码所示:
<?php
function isset_globals($method, $name, $option = "") {
if (isset($method[$name])) { // Check if such a variable
if ($option === "empty" && empty($method[$name])) { return false; } // Check if empty
if ($option === "stringLength" && strlen($method[$name])) { return strlen($method[$name]); } // Check length of string -- used when checking length of textareas
return ($method[$name]);
} else { return false; }
}
if (!isset_globals("$_post", "input_name", "empty")) {
echo "invalid";
} else {
/* You are safe to access the variable without worrying about errors! */
echo "you uploaded: " . $_POST["input_name"];
}
?>
回答by Mlutz
I'm not sure what your definition of readability is, but proper use of empty(), isset() and try/throw/catch blocks, is pretty important to the whole process. If your E_NOTICE is coming from $_GET or $_POST, then they should be checked against empty() right along with all the other security checks that that data should have to pass. If it's coming from external feeds or libraries, it should be wrapped in try/catch. If it's coming from the database, $db_num_rows() or it's equivalent should be checked. If it's coming from internal variables, they should be properly initialized. Often, these types of notices come from assigning a new variable to the return of a function that returns FALSE on a failure, those should be wrapped in a test that, in the event of a failure, can either assign the variable an acceptable default value that the code can handle, or throwing an exception that the code can handle. These things make the code longer, add extra blocks, and add extra tests, but I disagree with you in that I think they most definitely add extra value.
我不确定您对可读性的定义是什么,但正确使用 empty()、isset() 和 try/throw/catch 块对整个过程非常重要。如果您的 E_NOTICE 来自 $_GET 或 $_POST,那么它们应该与 empty() 以及该数据必须通过的所有其他安全检查一起检查。如果它来自外部提要或库,则应将其包装在 try/catch 中。如果它来自数据库,则应检查 $db_num_rows() 或其等效项。如果它来自内部变量,它们应该被正确初始化。通常,这些类型的通知来自将新变量分配给失败时返回 FALSE 的函数的返回值,这些通知应包含在测试中,如果出现故障,可以为变量分配代码可以处理的可接受的默认值,或者抛出代码可以处理的异常。这些东西使代码更长,添加额外的块,并添加额外的测试,但我不同意你的观点,我认为它们绝对增加了额外的价值。
回答by knoopx
Software does not magically run by the grace of god. If you are expecting something that is missing, you need to properly handle it.
软件并不是靠上帝的恩典神奇地运行的。如果您期待丢失的东西,您需要正确处理它。
If you ignore it, you are probably creating security holes in your applications. In static languages accessing a non-defined variable it is just not possible. It won't simply compile or crash your application if it's null.
如果您忽略它,您可能会在您的应用程序中创建安全漏洞。在静态语言中访问未定义的变量是不可能的。如果它为空,它不会简单地编译或崩溃您的应用程序。
Furthermore, it makes your application unmaintainable, and you are going to go mad when unexpected things happen. Language strictness is a must and PHP, by design, is wrong in so many aspects. It will make you a bad programmer if you are not aware.
此外,它会使您的应用程序无法维护,并且在发生意外情况时您会发疯。语言严格是必须的,而 PHP 从设计上来说,在很多方面都是错误的。如果你不知道,它会让你成为一个糟糕的程序员。

