Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/232.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何避免isset()和empty()_Php_Error Reporting - Fatal编程技术网

Php 如何避免isset()和empty()

Php 如何避免isset()和empty(),php,error-reporting,Php,Error Reporting,我有几个较旧的应用程序,它们在E_NOTICE错误级别上运行时会抛出大量“xyz未定义”和“未定义偏移量”消息,因为变量的存在不是使用isset()和consort显式检查的 我正在考虑通过它们使它们与E_NOTICE兼容,因为关于缺失变量或偏移量的通知可能是救命稻草,可能会获得一些小的性能改进,而且总体上是更干净的方式 然而,我不喜欢成百上千的isset()empty()和array\u key\u exists()s对我的代码造成的影响。它变得臃肿,可读性变差,没有任何价值或意义 如何在不进

我有几个较旧的应用程序,它们在E_NOTICE错误级别上运行时会抛出大量“xyz未定义”和“未定义偏移量”消息,因为变量的存在不是使用
isset()
和consort显式检查的

我正在考虑通过它们使它们与E_NOTICE兼容,因为关于缺失变量或偏移量的通知可能是救命稻草,可能会获得一些小的性能改进,而且总体上是更干净的方式

然而,我不喜欢成百上千的
isset()
empty()
array\u key\u exists()
s对我的代码造成的影响。它变得臃肿,可读性变差,没有任何价值或意义


如何在不进行过多变量检查的情况下构造代码,同时又能与E_NOTICE兼容?

只需为此编写一个函数即可。比如:

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;
    }
}
你可以把它当作

$username = get_string($_POST, 'username');

对于像
get_number()
get_boolean()
get_array()
等琐碎的东西也要这样做。

对于那些感兴趣的人,我将这个主题扩展成了一篇小文章,它以更好的结构化形式提供了以下信息:


我想你应该考虑的不仅仅是让应用程序“E_NOTICE兼容”,而是重新构建整个应用程序。代码中有数百个点经常试图使用不存在的变量,这听起来像是一个结构相当糟糕的程序。尝试访问不存在的变量是永远不会发生的,其他语言在编译时会对此犹豫不决。PHP允许您这样做并不意味着您应该这样做

这些警告是为了帮助你,而不是打扰你。如果您收到警告“您正在尝试使用不存在的东西!”,您的反应应该是“哎呀,我的坏东西,让我尽快修复它。”否则您将如何区分“工作正常的变量未定义”和可能导致严重错误的错误代码之间的区别?这也是为什么您总是、总是使用错误报告进行开发,并一直插入代码,直到没有发出一个
通知为止。关闭错误报告仅适用于生产环境,以避免信息泄漏,并提供更好的用户体验,即使在遇到错误代码时也是如此


详细说明:

您总是需要在代码中的某个地方设置
isset
empty
,减少它们出现的唯一方法是正确初始化变量。根据具体情况,有不同的方法:

函数参数:

function foo ($bar, $baz = null) { ... }
无需检查函数中是否设置了
$bar
$baz
,因为您只需设置它们,您只需担心它们的值是否计算为
true
false
(或其他任何值)

任意位置的正则变量:

$foo = null;
$bar = $baz = 'default value';
在要使用变量的代码块顶部初始化变量。这就解决了
!isset
问题,确保变量始终有一个已知的默认值,让读者了解以下代码将处理什么,从而也可以作为一种自我文档

阵列:

$defaults = array('foo' => false, 'bar' => true, 'baz' => 'default value');
$values = array_merge($defaults, $incoming_array);
与上面相同,您将使用默认值初始化数组,并使用实际值覆盖它们

在其余的情况下,假设您正在输出控制器可能设置或可能不设置的值的模板,您只需检查:

<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>

如上所述,如果正确初始化变量,则不需要检查该键是否存在,因为您知道它存在。如果从外部源获取数组,则值很可能不是
null
,而是
'
0
'0'
false
或类似值,即根据您的意图,可以使用
isset
empty
进行计算的值。如果您定期将数组键设置为
null
,并希望它表示除
false
以外的任何内容,即,如果在上面的示例中,
isset
array\u key\u存在的不同结果对您的程序逻辑产生影响,您应该问自己为什么。变量的存在本身并不重要,只有它的值才有意义。如果键是
true
/
false
标志,则使用
true
false
,而不是
null
。唯一的例外是希望
null
有意义的第三方库,但由于
null
在PHP中很难检测到,所以我还没有找到任何这样的库。

我和您在一起。但是PHP设计者犯了比这更严重的错误。除了为任何值读取定义自定义函数外,没有任何方法可以解决此问题。

我不确定您对可读性的定义是什么,但正确使用empty()、isset()和try/throw/catch块对整个过程非常重要

如果您的E_通知来自$\u GET或$\u POST,则应根据empty()以及该数据必须通过的所有其他安全检查对其进行检查

如果它来自外部提要或库,则应该用try/catch包装

如果它来自数据库,则应检查$db_num_rows()或其等效项

如果它来自内部变量,它们应该被正确初始化。通常,这些类型的通知来自为函数的返回指定一个新变量,该函数在失败时返回FALSE。这些应该包装在一个测试中,在发生故障时,该测试可以为变量分配一个可接受的默认值,代码可以处理该值,或者抛出一个代码可以处理的异常

这些东西使代码变长,增加额外的块,增加额外的测试,但我不同意你的观点
$array = array('key' => null);
isset($array['key']); // false
array_key_exists('key', $array); // true
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;
}
$arr1 = array
(
    'xyz' => 'value'
);

$arr2 = array
(
    'x' => array
    (
        'y' => array
        (
            'z' => 'value',
        ),
    ),
);
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');
$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';
}
$url = 'https://stackoverflow.com/questions/1960509';
$domain = Value(parse_url($url), 'host', 'N/A');
$ip = Value($_SERVER, 'HTTP_CLIENT_IP', Value($_SERVER, 'HTTP_X_FORWARDED_FOR', Value($_SERVER, 'REMOTE_ADDR')));
function load(&$var) { return isset($var) ? $var : null; }
function POST($var) { return isset($_POST[$var]) ? $_POST[$var] : null; }
$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";
}
if(@$foo) { /* Do something */ }
if(isset($foo) && $foo) { /* ... */ }
<?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"];
}
?>
$field = $_GET['field'] ?? null;