Ошибка в PHP с арифметикой bool в циклах - PullRequest
0 голосов
/ 28 марта 2011

Похоже, в 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 блоков.

Ответы [ 3 ]

8 голосов
/ 28 марта 2011

Проблема здесь в том, что оператор = имеет более высокий приоритет , чем and оператор.Таким образом, выражение присваивания является просто частью логического выражения, и все выражение эквивалентно этому:

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

Либо поместите логическое выражение в скобки, либо используйте && вместо and:

$allset = ($one->wasSet() and $allset);
$allset = $one->wasSet() && $allset;
1 голос
/ 28 марта 2011

Не должно быть

$allset = true;

перед вторым циклом foreach?

0 голосов
/ 28 марта 2011

(код ниже совместим только с php 5)

Ваш код содержит еще одну ошибку:

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

Должно быть

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

Также было бы лучше, если бы у вас был класс для формы вместо массива полей

Форма класса { защищенные поля $ = массив (); function addField ($ field) { $ this-> fields = $ field; вернуть поле $; } function allSet () { $ allSet = true; foreach ($ this-> fields как $ field) { $ allSet = $ allSet && $ field-> wasSet (); } return $ 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...
}

если вам нужно сделать один и тот же цикл дважды, ваш код уже грязный

...