use*_*303 3 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[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'][''])))
) {
}
Run Code Online (Sandbox Code Playgroud)
或者有没有更好的方法来做到这一点?
建议避免复杂的条件表达式,因为它们难以阅读和理解。但是,如果表达式仅使用一种类型的逻辑运算符来连接条件,则可以很容易理解。
例如:
if ($a && $b || $c && ! $d) {
echo("Yes!");
}
Run Code Online (Sandbox Code Playgroud)
你能一眼看出if分支( echo())中的代码什么时候执行吗?很可能不会。该表达式包含所有逻辑运算的混合,如果不绘制$a、$b、$c和的所有可能值的表,则很难评估其最终值$d。
另一方面,表达式:
if ($a && $b && $c && $d) {
echo("Hooray!");
}
Run Code Online (Sandbox Code Playgroud)
更容易掌握。当、 、和全部同时出现时,
该语句执行。echo()$a$b$c$dTRUE
就您而言,情况比上面介绍的第一个情况更复杂。它包含所有逻辑运算符和括号,并且子表达式相当长。
为了保持其可读性,我会将复杂的条件提取到返回布尔值(谓词)的(私有或受保护)方法中。
private function isValidData(array $data)
{
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'][''])))
) {
return TRUE;
} else {
return FALSE;
}
}
Run Code Online (Sandbox Code Playgroud)
并替换语句中的表达式if:
if ($this->isValidData($data)) {
}
Run Code Online (Sandbox Code Playgroud)
在接下来的步骤中,我会将复杂的条件表达式拆分为较小的条件,逐一测试它们,并在可能的情况下使函数尽早isValidData()返回 ( FALSE)。
由于表达复杂且片段相对较长,因此很难按原样使用它。这就是为什么,在第一步中,我将条件提取到具有较短名称的局部变量中($a,$b如上):
private function isValidData(array $data)
{
$a = array_key_exists(self::SUB_FORM_CONTACT, $data);
$b = array_key_exists('company', $data[self::SUB_FORM_CONTACT]);
$c = array_key_exists('salesRegion', $data[self::SUB_FORM_CONTACT]['company']);
$d = empty($data[self::SUB_FORM_CONTACT]['company']['salesRegion']);
$e = array_key_exists('serviceRegion', $data[self::SUB_FORM_CONTACT]['company']);
$f = empty($data[self::SUB_FORM_CONTACT]['company']['']);
// this should probably read 'serviceRegion' -------^
if ($a && $b && (($c && ! $d) || ($e && ! $f))) {
return TRUE;
} else {
return FALSE;
}
}
Run Code Online (Sandbox Code Playgroud)
现在一切看起来都很清楚了,我们甚至发现了一个错误。伟大的!
让我们尝试理清这个(现在更容易阅读)条件:
if ($a && $b && (($c && ! $d) || ($e && ! $f))) {
return TRUE;
} else {
return FALSE;
}
Run Code Online (Sandbox Code Playgroud)
如果我们一次进行一个测试并在结果明显后立即返回(TRUE或),可能会变得更容易理解。当和以及包含表达式其余部分的括号同时出现时,FALSE该函数返回。TRUE$a$bTRUE
该if语句可以这样重写:
if ($a) {
if ($b) {
if (($c && ! $d) || ($e && ! $f))) {
return TRUE;
}
}
}
return FALSE;
Run Code Online (Sandbox Code Playgroud)
通过反转 和 的条件$a,$b我们可以FALSE提前返回:
if (! $a) {
return FALSE;
}
if (! $b) {
return FALSE;
}
if (($c && ! $d) || ($e && ! $f))) {
return TRUE;
}
return FALSE;
Run Code Online (Sandbox Code Playgroud)
代码现在看起来像这样:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,因为从第二个开始的所有赋值都包含公共子表达式,所以$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']);
Run Code Online (Sandbox Code Playgroud)
让我们注意表达式中的内容$c && ! $d:
array_key_exists('salesRegion', $company) && ! empty($company['salesRegion'])
Run Code Online (Sandbox Code Playgroud)
调用 toarray_key_exists()并不是真正需要的。我猜它的目的是避免在$company['salesRegion']访问且不$company包含密钥时触发通知'salesRegion'。当数组中不存在该键并且不会触发通知时,PHPempty()构造将愉快地返回。TRUE
同样的情况也发生在$e && ! $f. 这使我们能够完全删除$c和$e。现在的情况是这样的:
if (! $d || ! $f) {
return TRUE;
}
Run Code Online (Sandbox Code Playgroud)
或者
if (! ($d && $f)) {
return TRUE;
}
Run Code Online (Sandbox Code Playgroud)
通过否定条件:
if ($d && $f) {
return FALSE;
} else {
return TRUE;
}
Run Code Online (Sandbox Code Playgroud)
完整的函数现在如下所示:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我们可以消除局部变量$a、和$b,并在知道它们不是之后移动和的初始化(每个变量都在对 的相应调用之后):$d$f$form$companyNULLarray_key_exists()
该函数的最终形式是这样的:
/**
* Verify if the provided data is valid.
*
* @param array $data the data to validate
* @return boolean TRUE if the data is valid, FALSE if some field is missing or empty
*/
private function isValidData(array $data)
{
// $data must contain the contact form information
if (! (array_key_exists(self::SUB_FORM_CONTACT, $data))) {
return FALSE;
}
// The contact form information exists in $data
$form = $data[self::SUB_FORM_CONTACT];
// The form must contain company information
if (! (array_key_exists('company', $form))) {
return FALSE;
}
// The company information exists in the contact form
$company = $form['company'];
// The company must contains information about salesRegion or serviceRegion or both
if (empty($company['salesRegion']) && empty($company['serviceRegion'])) {
return FALSE;
}
// The data is valid
return TRUE;
}
Run Code Online (Sandbox Code Playgroud)
该代码比以前长了几行,但是:
if ($this->isValidData($data))一眼就能明白那里发生了什么,而无需阅读和理解它是如何发生的;如果它有效,那就不用担心;