【问题标题】:Error in PHP with bool arithmetic in loops循环中带有布尔运算的PHP错误
【发布时间】:2011-07-24 10:33:55
【问题描述】:

在循环中使用布尔运算的 PHP 中似乎存在错误。

在这个特定的示例中,我测试是否设置了所有重要的表单字段(由对象表示)。 var_dump 用于调试目的。

$allset = true;
foreach ($forms as $one):
    $allset = $one->wasSet() and $allset;
endforeach;
var_dump($allset);
foreach ($more as $one):
    $allset = $one->wasSet() and $allset;
endforeach;
var_dump($allset);
$allset = $iwasthere->wasSet() and $allset;
var_dump($allset);

此代码可能会失败。可能第一个转储返回 false,第二个转储返回 true。

我的问题。

我怎样才能避免这个错误并拥有简洁干净的代码?


附言

我现在使用if 块。

【问题讨论】:

  • 当我发现有人使用foreach(): ... endforeach; 语法时,我仍然感到惊讶:-)
  • 我没有看到任何错误:?我也无法想象,$forms$more 应该包含什么。 @Alvaro:如果我混合使用 PHP/HTML,我会使用这种语法。很难找出} 属于哪个语句。 :)

标签: php loops boolean


【解决方案1】:

这里的问题是= 运算符有一个higher precedence 而不是and 运算符。所以赋值表达式只是逻辑表达式的一部分,整个表达式等价于:

($allset = $one->wasSet()) and $allset;

要么将逻辑表达式放在括号中,要么使用&& 代替and

$allset = ($one->wasSet() and $allset);
$allset = $one->wasSet() && $allset;

【讨论】:

  • 这是使用布尔表达式时应该遵循的最佳方法
【解决方案2】:

不应该有

$allset = true;

在第二个 foreach 循环之前?

【讨论】:

  • 没有。我想整体测试两个数组和一个“标量”的内容。 var_dump 用于调试目的。
  • 所以,你的意思是转储永远不应该返回(假,真),但其他 3 种组合应该是可能的。好的,我误解了你是如何在 2 循环中使用 $allset 的。
  • 我在两个数组($forms 和 $more)中有几个对象,一个名为 $iwasthere。对象有方法 wasSet() 返回 bool。我想测试是否所有对象都返回 true。
【解决方案3】:

(以下代码仅与 php 5 兼容)

您的代码有另一个错误:

$allset = $iwasthere->wasSet(); // this overwrites all previous checks

应该是

$allset = $iwasthere->wasSet() && $allset;

如果你有一个表单类而不是字段数组会更好

类形式{ 受保护的 $fields = array(); 函数添加字段($字段){ $this->fields = $field; 返回$字段; } 函数 allSet(){ $allSet = 真; foreach($this->fields as $field){ $allSet = $allSet && $field->wasSet(); } 返回 $allSet; } }

添加字段,您可以(选项一)扩展类:

RegisterForm extends Form{
  function __construct(){
    $name = $this->addField(new FormField('name'));
    $action = $this->addField(new FormField('action'));
    $action->hidden = true;
  }
}

然后你像这样使用它:

$form = new RegisterForm();

或者(选项二)您可以在创建表单后添加字段

$form = new Form();
$name = $form->addField(new FormField('name'));

....

然后使用非常简单:

....

if(!$form->allSet()){ // that looks like clean code
  ...error...
}

如果您有 2 个表格:

$allSet = $form1->allSet() && $form2->allSet();
if( !$allSet ){
  ...error...
}

如果你需要重复两次相同的循环,你的代码已经很枯燥​​了

【讨论】:

  • 这是一个非常小的项目。不写类的代码就少了。
  • 好吧,你要求一个干净的代码。如果它是一个小项目,那么为什么表单字段是对象?我会为你编写课程:class FormField{protected $fields; function addField($field){$fields[] = $field;} function allSet(){/* 把你的循环放在这里——无论如何你都必须写它*/}}。没有超过一分钟。它与整个项目的时间相比如何(即使项目必须进行一小时)。
  • 我使用表单字段的类主要是为了生成html标签。在我对干净代码的定义中,为一个方法创建一个完整的类是不干净的。
  • 当然你会有其他方法——它们会伴随着你需要编写其他代码的需要。我的意思是在类中编写它的开销并不大,因为无论如何你都要编写代码,唯一的区别是在类中它将按功能打包和分组。我敢打赌,你有很多代码在不知名的地方获取表单发布数据并为每个字段创建对象。您可以将此代码放入 Form 类中。你不需要总是使用面向对象的编程——你可以使用类来对函数和数据进行分组。它更干净。
猜你喜欢
  • 2020-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-20
  • 2013-08-09
  • 2015-05-24
  • 1970-01-01
相关资源
最近更新 更多