检查变量是否设置并且可以"foreach"的最佳方法



我接管了一个更大的代码库,其中有几个警告和错误。

我不断遇到这样的说法:

foreach( $object->keys => $key ){
...
}

在错误日志中,我可以看到$object为null。

最简单的方法是什么,来检查上面的书面陈述不会破裂?


为了100%确定,我会做这样的事情:

if( isset( $object ) && is_array( $object->keys ) ){
foreach( $object->keys => $key ){
...
}
}

但是可读性明显下降。

我还可以制作一个助手函数,这样就可以了:

if( myHelper::canBeForeached( $object, 'keys' ) ){ // naming would obviously be changed
foreach( $object->keys => $key ){
...
}
}

但这似乎也很糟糕。

实现这一点,同时保持代码可读性的最简单/最漂亮的方法是什么?

有很多方法可以实现这一点。这是最短的方法。

如果使用??null合并运算符作为默认值,则在未定义$object->keys的情况下,将传递[]或空数组进行迭代,显然不会发生任何事情。这是避免将foreach循环封装在条件中的一种方法。

foreach($object->keys ?? [] as $key) {
// If $object or ->keys is undefined, nothing happens.
}

现在,有些人可能会反对这是不清楚无法读取;但至少它不是一个样板,而且添加起来很快。这种方法假设如果$object存在并且具有属性keys,那么keys将是可迭代的。否则,将导致上的警告。必须是array|object类型。

除此之外,如果您想确保它是一个对象,则必须使用条件检查isset($object)gettype($object) === 'object'来包装所有循环。由于某种原因,is_object()将对未定义的变量发出警告。同样,如果变量未定义,则is_null()返回true,在取反时基本上表现为!isset()

如上所述,如果您的遗留代码具有多个命名属性的对象,这些属性不可迭代,但也不为null(例如->keys = 'duck'(,则在$object->keys进入循环尝试迭代之前,您必须使用is_iterable()对其进行检查。

如果将未定义的对象传递到is_iterable中,则再次发出警告。然而,您可以再次使用null合并的功能,其中,如果$object->keys未定义,则下面的检查读取为is_iterable(false)(或要评估的任何其他不可迭代值(:

if(is_iterable($object->keys ?? false)) { 
foreach($object->keys as $key) {
//...
}
}

这可能是包裹你的循环的唯一条件。

附言:关于OP中可能的解决方案:如果与未定义的变量一起使用,辅助函数会导致警告。此外,如果定义了object但没有->keys属性,则if( isset( $object ) && is_array( $object->keys ) )将导致警告。

最新更新