我正在处理前一位开发人员完成的一些代码。我是PHP的新手,所以我想知道是否有任何众所周知的模式或解决方案来解决这个问题。
基本上,原作者在尝试使用它们之前不会检查任何数组索引。我知道我可以使用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 */
所以我知道我可以在这里为每个项目使用isset()。我将不得不重新安排一些事情并删除现在的所有连接。有没有其他简单的方法可以做到这一点,还是我只是坚持下去?
答案 0 :(得分:22)
找出$ 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] = '';
}
答案 1 :(得分:11)
您可以使用isset()而不会丢失连接:
//snip
$str = 'something'
. ( isset($output['alternate_title']) ? $output['alternate_title'] : '' )
. ( isset($output['access_info']) ? $output['access_info'] : '' )
. //etc.
如果设置了字符串,你也可以写一个函数来返回字符串 - 这可能效率不高:
function getIfSet(& $var) {
if (isset($var)) {
return $var;
}
return null;
}
$str = getIfSet($output['alternate_title']) . getIfSet($output['access_info']) //etc
您不会收到通知,因为该变量是通过引用传递的。
答案 2 :(得分:7)
SquareRootOf2答案的变体,但这应该在第一次使用$ output变量之前放置:
$keys = array('key1', 'key2', 'etc');
$output = array_fill_keys($keys, '');
答案 3 :(得分:5)
如果您要维护旧代码,那么您可能无法瞄准“有史以来最好的代码”......在我看来,这可能会降低error_reporting
级别。
这些“未定义索引”应仅为通知;因此,您可以设置error_reporting
级别以排除通知。
一个解决方案是使用error_reporting
函数,如下所示:
// Report all errors except E_NOTICE
error_reporting(E_ALL ^ E_NOTICE);
此解决方案的好处是您可以将其设置为仅在必要时排除通知(例如,如果只有一个或两个文件具有此类代码)
另一个解决方案是在php.ini中设置它(如果您正在处理多个应用程序,可能不是一个好主意,因为它可能会掩盖有用的通知);请参阅php.ini中的error_reporting
。
但我坚持认为:这只是因为你维护一个旧的应用程序是可以接受的 - 在开发新代码时你不应该这样做!
答案 4 :(得分:4)
在开头(或使用$output
数组之前)设置数组中的每个索引可能是最简单的解决方案。
实施例
$output['admin_link'] = ""
$output['alternate_title'] = ""
$output['access_info'] = ""
$output['description'] = ""
$output['url'] = ""
也不是真的与你的情况有关,但你说你是PHP的新手并不是很明显isset()
可以采取多个参数。所以取而代之的是:
if(isset($var1) && isset($var2) && isset($var3) ...){
// all are set
}
你可以这样做:
if(isset($var1, $var2, $var3)){
// all are set
}
答案 5 :(得分:2)
这是一个简短的解决方案(PHP 5.3 +):
$output['alternate_title'] = $output['alternate_title'] ?:'';
您可以获得变量的值,如果它没有计算为false,或者获得false表达式。 (':'之后的那个)
使用没有“if true”参数的三元运算符将返回测试表达式的结果(第一个)由于undefined计算结果为false,因此将返回false表达式。
在PHP 7中,有一个更优雅的Null合并运算符:
$output['alternate_title'] = $output['alternate_title'] ?? '';
(对于像'?='这样的默认赋值运算符会很好。
答案 6 :(得分:2)
这是我能想到的最快的解决方案,但到目前为止还不是最好的。因此,将其视为“紧急解决方案”:
// ...
. @$output['admin_link']
. @$output['alternate_title']
. @$output['access_info']
// ...
@
会抑制所有PHP警告和错误。
答案 7 :(得分:1)
与Michael Waterfall相同的想法
// 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];
}
答案 8 :(得分:0)
就我而言,如果提交的数据为空,则可以通过定义默认值来使其正常工作。这是我最终(使用PHP7.3.5)所做的事情:
if(empty($_POST['auto'])){
$_POST['auto'] = "";
}
答案 9 :(得分:-2)
您可以尝试使用一个很好的小函数,如果它存在则返回值,否则返回一个空字符串。这就是我使用的:
function arrayValueForKey($arrayName, $key) {
if (isset($GLOBALS[$arrayName]) && isset($GLOBALS[$arrayName][$key])) {
return $GLOBALS[$variable][$key];
} else {
return '';
}
}
然后你可以像这样使用它:
echo ' Values: ' . arrayValueForKey('output', 'admin_link')
. arrayValueForKey('output', 'update_frequency');
它不会引起任何错误!
希望这有帮助!
答案 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);
}