PHP 数组和“未定义索引”错误的解决方案

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1195549/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 01:28:07  来源:igfitidea点击:

PHP arrays and solution to 'undefined index' errors

phparrays

提问by

I am working through some code done by a previous developer. I'm pretty new to PHP so I am wondering if there is any well known pattern or solution to this problem.

我正在处理由以前的开发人员完成的一些代码。我对 PHP 很陌生,所以我想知道这个问题是否有任何众所周知的模式或解决方案。

Basically the original author does not check any array indexes before he tries to use them. I know I can use isset() to check each before it is used, but right now there are hundreds of lines where these errors are appearing. Before I put on some music and start slamming my head into my keyboard I want to make sure there is not some nice shortcut for handling this. Here is a typical section of code I'm looking at:

基本上,原作者在尝试使用它们之前不会检查任何数组索引。我知道我可以在使用 isset() 之前对其进行检查,但现在有数百行出现这些错误。在我放一些音乐并开始用我的头撞键盘之前,我想确保没有一些很好的快捷方式来处理这个问题。这是我正在查看的典型代码部分:

    /* snip */
"text" => $link . $top_pick_marker . $output['author'] . " " .  " " . 
                              $output['new_icon'] . $output['rec_labels'] . "   " 
                    . $output['admin_link']
                    . $output['alternate_title'] 
                    . $output['access_info'] 
                    . $output['description'] 
                    . $output['url']
                    . $output['subject_terms'] 
                    . $output['form_subdivisions'] 
                    . $output['dates_of_coverage']  
                    . $output['update_frequency']  
                    . $output['place_terms'],
    /* snip */

So I know I can use isset() here for each item. I would have to rearrange things a bit and remove all the concatenation as it is now. Is there any other easy way to do this or am I just stuck with it?

所以我知道我可以在这里为每个项目使用 isset() 。我将不得不重新排列一些东西并像现在一样删除所有连接。有没有其他简单的方法可以做到这一点,还是我只是坚持下去?

采纳答案by SquareRootOf2

Figure out what keys are in the $output array, and fill the missing ones in with empty strings.

找出 $output 数组中的键,并用空字符串填充缺失的键。

$keys = array_keys($output);
$desired_keys = array('author', 'new_icon', 'admin_link', 'etc.');

foreach($desired_keys as $desired_key){
   if(in_array($desired_key, $keys)) continue;  // already set
   $output[$desired_key] = '';
}

回答by Tom Haigh

You can use isset() without losing the concatenation:

您可以使用 isset() 而不会丢失连接:

//snip
$str = 'something'
 . ( isset($output['alternate_title']) ? $output['alternate_title'] : '' )
 . ( isset($output['access_info']) ? $output['access_info'] : '' )
 . //etc.

You could also write a function to return the string if it is set - this probably isn't very efficient:

如果设置了字符串,您还可以编写一个函数来返回字符串 - 这可能不是很有效:

function getIfSet(& $var) {
    if (isset($var)) {
        return $var;
    }
    return null;
}

$str = getIfSet($output['alternate_title']) . getIfSet($output['access_info']) //etc

You won't get a notice because the variable is passed by reference.

您不会收到通知,因为该变量是通过引用传递的。

回答by Sterling Hirsh

A variation on SquareRootOf2's answer, but this should be placed before the first use of the $output variable:

SquareRootOf2 答案的变体,但这应该放在第一次使用 $output 变量之前:

$keys = array('key1', 'key2', 'etc');
$output = array_fill_keys($keys, '');

回答by Pascal MARTIN

If you are maintaining old code, you probably cannot aim for "the best possible code ever"... That's one case when, in my opinion, you could lower the error_reportinglevel.

如果您正在维护旧代码,您可能无法以“有史以来最好的代码”为目标……这是一种情况,在我看来,您可以降低error_reporting级别。

These "undefined index" should only be Notices ; so, you could set the error_reportinglevel to exclude notices.

这些“未定义索引”应该只是通知;因此,您可以设置error_reporting级别以排除通知。

One solution is with the error_reportingfunction, like this :

一种解决方案是使用该error_reporting功能,如下所示:

// Report all errors except E_NOTICE
error_reporting(E_ALL ^ E_NOTICE);

The good thing with this solution is you can set it to exclude notices only when it's necessary (say, for instance, if there is only one or two files with that kind of code)

此解决方案的好处是您可以将其设置为仅在必要时排除通知(例如,如果只有一两个文件具有这种代码)

One other solution would be to set this in php.ini (might not be such a good idea if you are working on several applications, though, as it could mask useful notices ) ; see error_reportingin php.ini.

另一种解决方案是在 php.ini 中设置它(如果您正在处理多个应用程序,这可能不是一个好主意,因为它可能会掩盖有用的通知);见error_reportingphp.ini。

But I insist : this is acceptable only because you are maintaining an old application -- you should not do that when developping new code !

但我坚持:这是可以接受的,因为您正在维护一个旧的应用程序 - 在开发新代码时不应该这样做!

回答by MitMaro

Set each index in the array at the beginning (or before the $outputarray is used) would probably be the easiest solution for your case.

在开始时(或在使用$output数组之前)设置数组中的每个索引可能是最简单的解决方案。

Example

例子

$output['admin_link'] = ""
$output['alternate_title'] = ""
$output['access_info'] = ""
$output['description'] = ""
$output['url'] = ""


Also not really relevant for your case but where you said you were new to PHP and this is not really immediately obvious isset()can take multiple arguments. So in stead of this:

也与您的情况无关,但是您说您是 PHP 新手并且这不是很明显isset()可以采用多个参数。所以代替这个:

if(isset($var1) && isset($var2) && isset($var3) ...){
    // all are set
}

You can do:

你可以做:

if(isset($var1, $var2, $var3)){
   // all are set 
}

回答by Simon Rigét

A short solution is this (PHP 5.3+):

一个简短的解决方案是这样的(PHP 5.3+):

$output['alternate_title'] = $output['alternate_title'] ?:'';

You get either the value of the variable, if it doesn't evaluate to false, or the false expression. (The one after the ':')

您将获得变量的值(如果它的计算结果不为 false)或 false 表达式。(':' 后面的那个)

Using the ternary Operator, without the "if true" parameter, will return the result of the test expression (The first one ) Since undefined evaluates to false, the false expression will be returned.

使用三元运算符,不带“if true”参数,将返回测试表达式的结果(第一个)由于 undefined 的计算结果为 false,因此将返回 false 表达式。

In PHP 7 there is the slightly more elegant Null coalescing operator:

在 PHP 7 中有更优雅的 Null 合并运算符:

$output['alternate_title'] = $output['alternate_title'] ?? '';

(It would be nice with a default assignment operator like '?=')

(使用像 '?=' 这样的默认赋值运算符会很好)

回答by Kai Noack

This is the fastest solution I can think of, but by far not the best. So see it as an "emergency solution":

这是我能想到的最快的解决方案,但到目前为止还不是最好的。因此,将其视为“紧急解决方案”:

// ...
. @$output['admin_link']
. @$output['alternate_title'] 
. @$output['access_info'] 
// ... 

The @suppresses all PHP warnings and errors.

@抑制所有PHP警告和错误。

回答by Jerome Jaglale

Same idea as Michael Waterfall

与迈克尔瀑布相同的想法

From CodeIgniter

来自CodeIgniter

// Lets you determine whether an array index is set and whether it has a value.
// If the element is empty it returns FALSE (or whatever you specify as the default value.)
function element($item, $array, $default = FALSE)
{
    if ( ! isset($array[$item]) OR $array[$item] == "")
    {
        return $default;
    }

    return $array[$item];
}

回答by Jodyshop

In my case, I get it worked by defining the default valueif the submitted data is empty. Here is what I finally did (using PHP7.3.5):

就我而言,如果提交的数据为空,我会通过定义默认值来使其工作。这是我最终做的(使用 PHP7.3.5)

if(empty($_POST['auto'])){ $_POST['auto'] = ""; }

if(empty($_POST['auto'])){ $_POST['auto'] = ""; }

回答by Michael Waterfall

You could try using a nice little function that will return the value if it exists or an empty string if not. This is what I use:

您可以尝试使用一个不错的小函数,如果存在则返回值,否则返回空字符串。这是我使用的:

function arrayValueForKey($arrayName, $key) {
   if (isset($GLOBALS[$arrayName]) && isset($GLOBALS[$arrayName][$key])) {
      return $GLOBALS[$variable][$key];
   } else {
      return '';
   }
}

Then you can use it like this:

然后你可以像这样使用它:

echo ' Values: ' . arrayValueForKey('output', 'admin_link') 
                 . arrayValueForKey('output', 'update_frequency');

And it won't throw up any errors!

它不会抛出任何错误!

Hope this helps!

希望这可以帮助!