Php 在if语句中使用大量和条件好吗?

Php 在if语句中使用大量和条件好吗?,php,arrays,if-statement,Php,Arrays,If Statement,我有一个类似这样的代码,我只是想知道在一个if语句中使用大量的“and”或“or”是否是一个好习惯 if (array_key_exists(self::SUB_FORM_CONTACT, $data) && array_key_exists('company', $data[self::SUB_FORM_CONTACT]) && ((array_key_exists('salesRegion', $data[sel

我有一个类似这样的代码,我只是想知道在一个if语句中使用大量的“and”或“or”是否是一个好习惯

if (array_key_exists(self::SUB_FORM_CONTACT, $data) &&
            array_key_exists('company', $data[self::SUB_FORM_CONTACT]) &&
            ((array_key_exists('salesRegion', $data[self::SUB_FORM_CONTACT]['company']) && !empty($data[self::SUB_FORM_CONTACT]['company']['salesRegion'])) ||
                (array_key_exists('serviceRegion', $data[self::SUB_FORM_CONTACT]['company']) && !empty($data[self::SUB_FORM_CONTACT]['company'][''])))
        ) {

        }

或者有更好的方法吗?

在可读性方面,您应该正确设置代码的格式,一切都应该很好(给定示例中的格式设置是可以的)。在调试方面,在定义哪个语句失败时可能会出现一些问题,但如果格式正确,您只需注释掉几行easyli并检查结果即可。就性能而言,我认为它甚至更好。我的意思是,无论如何,你必须检查所有这些条件。如果你把它们都放在单独的If中,它们会一个接一个地被检查(好吧,你可以这样写,不是所有的都被检查,但我认为这只是不必要地延长了你的代码)。如果你的陈述写得正确,不是所有的都要检查。例如,对于大量的
&&
,如果第一个条件为false,则下一个条件甚至不会被检查。你应该把可能性更小、更轻(就性能而言)的条件放在最前面,而把可能更重的条件放在最后。如果您想保持主代码干净,您也可以将其封装在函数中。

PHP使If语句短路。因此,如果您有许多if子句

   if ($condition1 && $condition2 && $condition3 && $condition4)
一旦第一个表达式为false,PHP就会停止计算该表达式

要优化代码,请对表达式进行排序,以便首先计算最有可能出现故障的表达式

参考资料:


这是一个性能不佳的解决方案。然而,一般来说,当处理表单时,如果它是地球上最有效的东西,我就不太在乎了——它不是内核代码。我刚刚解决了一个类似的问题,向它扔了192吉比特的内存。。。。。在此基础上,它将为我节省数百到数千个开发小时,这比ram的成本要高得多

$hasdata            = array_key_exists(self::SUB_FORM_CONTACT, $data);
$hasCompany         = array_key_exists('company', $data[self::SUB_FORM_CONTACT]);
$hasSalesRegion     = array_key_exists('salesRegion', $data[self::SUB_FORM_CONTACT]['company']) 
$hasSalesRegion     = $hasSalesRegion && !empty($data[self::SUB_FORM_CONTACT]['company']['salesRegion']);
$hasServiceRegion   = array_key_exists('serviceRegion', $data[self::SUB_FORM_CONTACT]['company']) 
$hasServiceRegion   = $hasServiceRegion && !empty($data[self::SUB_FORM_CONTACT]['company']);

$evalResult = $hasdata && $hasCompany && ($hasSalesRegion || $hasServiceRegion);

if($evalResult)
{
    // do your thing
}


我更愿意看到这样的东西,而不是从简单易懂的双重否定中获益。

建议避免复杂的条件表达式,因为它们很难阅读和理解。但是,如果表达式只使用一种类型的逻辑运算符来连接条件,那么它就很容易理解

例如:

if ($a && $b || $c && ! $d) {
    echo("Yes!");
}
您能否一眼就知道
if
分支(
echo()
)中的代码何时执行?很可能不是。表达式包含所有逻辑运算的混合,如果不绘制
$a
$b
$c
$d
的所有可能值的表,则很难计算其最终值

另一方面,表达式:

if ($a && $b && $c && $d) {
    echo("Hooray!");
}
更容易掌握。
echo()
语句在所有
$a
$b
$c
$d
同时为
真时执行

重构 在您的情况下,情况比上面介绍的第一个更复杂。它包含所有逻辑运算符和括号,子表达式相当长

为了保持可读性,我将把复杂条件提取到一个(私有或受保护)方法中,该方法返回一个布尔值(谓词)

并替换
if
语句中的表达式:

if ($this->isValidData($data)) {
}
在接下来的步骤中,我将把复杂的条件表达式拆分成更小的条件,逐个测试它们,并尽可能早地使函数
isValidData()
返回(
FALSE

第一步 因为表达式很复杂,而且片段相对较长,所以很难按原样使用它。这就是为什么在第一步中,我会将条件提取到具有较短名称的局部变量中(
$a
$b
a.s.o.)

现在一切看起来都很清楚了,我们甚至发现了一个bug。太好了

步骤2 让我们尝试解开这个(现在更容易理解)条件:

if ($a && $b && (($c && ! $d) || ($e && ! $f))) {
    return TRUE;
} else {
    return FALSE;
}
if ($d && $f) {
    return FALSE;
} else {
    return TRUE;
}
如果我们一次做一个测试,并在结果明显时立即返回(
TRUE
FALSE
),可能更容易理解。 当
$a
$b
以及包含表达式其余部分的括号同时都为
TRUE
时,函数返回
TRUE

if
语句可以这样重写:

if ($a) {
    if ($b) {
        if (($c && ! $d) || ($e && ! $f))) {
            return TRUE;
        }
    }
}

return FALSE;
通过反转
$a
$b
上的条件,我们可以提前返回
FALSE

if (! $a) {
    return FALSE;
}
if (! $b) {
    return FALSE;
}

if (($c && ! $d) || ($e && ! $f))) {
    return TRUE;
}
return FALSE;
代码现在如下所示:

private function isValidData(array $data)
{
    $a = array_key_exists(self::SUB_FORM_CONTACT, $data);
    $form = $data[self::SUB_FORM_CONTACT];

    $b = array_key_exists('company', $form);

    $c = array_key_exists('salesRegion', $form['company']);
    $d = empty($form['company']['salesRegion']);

    $e = array_key_exists('serviceRegion', $form['company']);
    $f = empty($form['company']['serviceRegion']);


    if (! $a) {
        return FALSE;
    }
    if (! $b) {
        return FALSE;
    }

    if (($c && ! $d) || ($e && ! $f))) {
        return TRUE;
    }
}
if (! $d || ! $f) {
    return TRUE;
}
private function isValidData(array $data)
{
    $a = array_key_exists(self::SUB_FORM_CONTACT, $data);
    $form = $data[self::SUB_FORM_CONTACT];

    $b = array_key_exists('company', $form);
    $company = $form['company'];

    $d = empty($company['salesRegion']);
    $f = empty($company['serviceRegion']);


    if (! $a) {
        return FALSE;
    }
    if (! $b) {
        return FALSE;
    }

    if ($d && $f) {
        return FALSE;
    } else {
        return TRUE;
    }
}
请注意,由于从第二个赋值开始的所有赋值都包含公共子表达式
$data[self::sub_FORM_CONTACT]
,因此我们将其提取到局部变量中。这同样适用于最后4个赋值(提取公共子表达式
$form['company']

// ...
$b = array_key_exists('company', $form);
$company = $form['company'];

$c = array_key_exists('salesRegion', $company);
$d = empty($company['salesRegion']);

$e = array_key_exists('serviceRegion', $company);
$f = empty($company['serviceRegion']);
步骤3 让我们注意到,在表达式
$c&!$d
中:

array_key_exists('salesRegion', $company) && ! empty($company['salesRegion'])
调用
array\u key\u exists()
并不是真的需要。我想它的目的是避免在访问
$company['salesRegion']
并且
$company
不包含键
'salesRegion'
时触发通知。
为空()
PHP构造将愉快地返回
TRUE
当数组中不存在键并且它不会触发通知时

$e&&!$f
也会发生同样的情况。这允许我们完全删除
$c
$e
。现在的情况如下所示:

private function isValidData(array $data)
{
    $a = array_key_exists(self::SUB_FORM_CONTACT, $data);
    $form = $data[self::SUB_FORM_CONTACT];

    $b = array_key_exists('company', $form);

    $c = array_key_exists('salesRegion', $form['company']);
    $d = empty($form['company']['salesRegion']);

    $e = array_key_exists('serviceRegion', $form['company']);
    $f = empty($form['company']['serviceRegion']);


    if (! $a) {
        return FALSE;
    }
    if (! $b) {
        return FALSE;
    }

    if (($c && ! $d) || ($e && ! $f))) {
        return TRUE;
    }
}
if (! $d || ! $f) {
    return TRUE;
}
private function isValidData(array $data)
{
    $a = array_key_exists(self::SUB_FORM_CONTACT, $data);
    $form = $data[self::SUB_FORM_CONTACT];

    $b = array_key_exists('company', $form);
    $company = $form['company'];

    $d = empty($company['salesRegion']);
    $f = empty($company['serviceRegion']);


    if (! $a) {
        return FALSE;
    }
    if (! $b) {
        return FALSE;
    }

    if ($d && $f) {
        return FALSE;
    } else {
        return TRUE;
    }
}

通过否定条件:

if ($a && $b && (($c && ! $d) || ($e && ! $f))) {
    return TRUE;
} else {
    return FALSE;
}
if ($d && $f) {
    return FALSE;
} else {
    return TRUE;
}
现在,完整的函数如下所示:

private function isValidData(array $data)
{
    $a = array_key_exists(self::SUB_FORM_CONTACT, $data);
    $form = $data[self::SUB_FORM_CONTACT];

    $b = array_key_exists('company', $form);

    $c = array_key_exists('salesRegion', $form['company']);
    $d = empty($form['company']['salesRegion']);

    $e = array_key_exists('serviceRegion', $form['company']);
    $f = empty($form['company']['serviceRegion']);


    if (! $a) {
        return FALSE;
    }
    if (! $b) {
        return FALSE;
    }

    if (($c && ! $d) || ($e && ! $f))) {
        return TRUE;
    }
}
if (! $d || ! $f) {
    return TRUE;
}
private function isValidData(array $data)
{
    $a = array_key_exists(self::SUB_FORM_CONTACT, $data);
    $form = $data[self::SUB_FORM_CONTACT];

    $b = array_key_exists('company', $form);
    $company = $form['company'];

    $d = empty($company['salesRegion']);
    $f = empty($company['serviceRegion']);


    if (! $a) {
        return FALSE;
    }
    if (! $b) {
        return FALSE;
    }

    if ($d && $f) {
        return FALSE;
    } else {
        return TRUE;
    }
}
最后一步 现在,我们可以消除局部变量
$a
$b
$d
$f
,并在我们知道它们不是
NULL
后移动
$form
$company
的初始化(每个都在对
数组的相应调用后存在()
):

T