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

时间:2022-10-17 11:20:14

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()来表示每一项。我将不得不重新安排一些事情并删除所有的连接。有没有其他简单的方法来做这件事呢?

10 个解决方案

#1


22  

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] = '';
}

#2


10  

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.

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

#3


7  

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, '');

#4


5  

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_reporting level.

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

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

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

One solution is with the error_reporting function, 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_reporting in php.ini.

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

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

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

#5


4  

Set each index in the array at the beginning (or before the $output array 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 
}

#6


2  

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警告和错误。

#7


2  

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,要么是假表达式。(在':'后面的那个)

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”参数)将返回测试表达式的结果(第一个),因为未定义的计算值为false,因此将返回false表达式。

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

在PHP 7中,有一个更优雅的零合并运算符:

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

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

(使用'?='这样的默认赋值操作符会更好)

#8


1  

Same idea as Michael Waterfall

和Michael瀑布一样

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];
}

#9


-2  

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!

希望这可以帮助!

#10


-3  

foreach($i=0; $i<10; $i++){
    $v = @(array)$v;   
    // this could help defining $v as an array. 
    //@ is to supress undefined variable $v

    array_push($v, $i);
}

#1


22  

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] = '';
}

#2


10  

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.

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

#3


7  

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, '');

#4


5  

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_reporting level.

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

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

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

One solution is with the error_reporting function, 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_reporting in php.ini.

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

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

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

#5


4  

Set each index in the array at the beginning (or before the $output array 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 
}

#6


2  

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警告和错误。

#7


2  

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,要么是假表达式。(在':'后面的那个)

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”参数)将返回测试表达式的结果(第一个),因为未定义的计算值为false,因此将返回false表达式。

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

在PHP 7中,有一个更优雅的零合并运算符:

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

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

(使用'?='这样的默认赋值操作符会更好)

#8


1  

Same idea as Michael Waterfall

和Michael瀑布一样

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];
}

#9


-2  

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!

希望这可以帮助!

#10


-3  

foreach($i=0; $i<10; $i++){
    $v = @(array)$v;   
    // this could help defining $v as an array. 
    //@ is to supress undefined variable $v

    array_push($v, $i);
}