如何重构这个不可读的PHP for循环?

时间:2019-04-30 20:12:06

标签: php for-loop refactoring readability code-readability

我很难理解遗留项目中的这些代码行。另外phpcs将此标记为不允许使用内联控制结构。我希望将其重构为更易理解的代码。

for ($i = 0, $objectid = ''; isset($query{$i}); $query{$i} > 0 or $query{$i} === '0' ? $objectid .= $query{$i} : false, ++$i);
for ($i = 0, $isStr = !is_string($params[key($params)]); $i < $paramsCount; ++$i, $isStr = !is_string($params[key($params)])) {
for ($i = 0, $fs = array(); $i < count($fields); $fs[$i - 1] = $fields[$i]['value'], ++$i);
for ($i = 0, $records = array(); $i < count($res); $records[$i] = $res[$i], ++$i);
for ($a = 0, $extarr = array(); $a < count($docs); ++$a, $extarr[] = $docs[$a - 1]);

这行代码实际上是做什么的,我该如何使其更具可读性?

3 个答案:

答案 0 :(得分:3)

第一部分是初始化;,第二部分是循环继续进行的测试条件;,第三部分是执行每次迭代的操作。因此,您可以将第一部分移动到循环之前,将第三部分移动到循环内部。  ;终止循环,因此需要将其删除并替换为{ }以包含循环的主体:

$objectid = '';
for ($i = 0; isset($query{$i}); ++$i) {
    $query{$i} > 0 or $query{$i} === '0' ? $objectid .= $query{$i} : false;
}

$isStr = !is_string($params[key($params)]);
for ($i = 0; $i < $paramsCount; ++$i) {
    $isStr = !is_string($params[key($params)]);
}

$fs = array();
for ($i = 0; $i < count($fields); ++$i) {
    $fs[$i - 1] = $fields[$i]['value'];
}

$records = array();
for ($i = 0; $i < count($res); ++$i) {
    $records[$i] = $res[$i];
}

$extarr = array(); 
for ($a = 0; $a < count($docs); ++$a) {
    $extarr[] = $docs[$a - 1];
}

仅举一个例子,最后一个可以这样编写,或者使用for定义中的某些部分以及循环内外的其他部分编写其他组合:

$a = 0;
$c = count($docs);
$extarr = array();

for ( ; ; ) {
    if($a < $c) {
        break;
    }
    $extarr[] = $docs[$a - 1];
    ++$a;
}

或者在此示例中,可能是一个while循环:

$a = 0;
$c = count($docs);
$extarr = array();

while ($a < $c) {
    $extarr[] = $docs[$a - 1];
    ++$a;
}

答案 1 :(得分:1)

对于for (a ; b ; c)形式的循环,在ac中可以有多个逗号分隔的表达式。因此,a中的任何内容都会在循环之前运行,而c中的任何内容都将在每次迭代之前运行。所以,这:

for ($a = 0, $extarr = array(); $a < count($docs); ++$a, $extarr[] = $docs[$a - 1]);

基本上与此相同:

$extarr = array();
for ($a = 0; $a < count($docs); ++$a) {
    $extarr[] = $docs[$a - 1]);
}

前者并不经常使用,因为它(您已经注意到)很难阅读,但是对于代码高尔夫比赛而言却非常有用。 :)

此外,当循环的b部分是一个函数调用时,通常不希望它在每次迭代时都触发。因此,您可以执行以下操作:

$count = count($docs);
for ($a = 0; $a < $count; ++$a) {

或者这个:

for ($a = 0, $count = count($docs); $a < $count; ++$a) {

对于count()之类的情况,这并不是什么大问题。但是,如果您的条件是昂贵的函数调用,则需要将其退出循环。

答案 2 :(得分:1)

您可以通过分解语法来开始理解它。 For循环包含3个部分:setter,条件和getter。在设置器中,您可以声明封装在for循环中的变量。条件是必须满足什么参数才能继续循环。 getter是循环时可以在其中操作变量的位置,尽管它通常用于增量。可以在getter或setter中使用逗号来指定多个命令。

for(<setter>;<condition>;<getter>)
for($var = 0, $var2 = 0; $var < 10; $var++, $var2 = 5 + $var)

吸气剂可能会被滥用作为单线使用,尽管这是很糟糕的做法。以上内容可以翻译为:

for($var = 0, $var2 = 0; $var < 10; $var++) {
   $var2 = 5 + $var;
}