Урок 13. Приемы работы с флагами в PHP
Теория
Флаг - это специальная переменная, которая может принимать только 2 значения: true или false. С помощью флагов можно решать задачи, проверяющие отсутствие чего-либо. Например, можно проверить, что в массиве нет элемента с определенным значением.
Флаги
Дан массив, нужно проверить, есть ли в нем элемент со значением 'c' или нет. Если есть, вывести 'есть', если нет, вывести 'нет'.
Сначала выводим 'есть'. Для этого перебираем все элементы массива и ифом будем спрашивать, равен ли текущий элемент значению 'c'. Если равен, выведем 'есть':
<?$a=['c','d'];foreach($a as$e){if($e=='c'){echo'Есть';}}?>
Есть
Решение не очень хорошо, ведь если в массиве будет не 1 значение 'c', а несколько, то echo выведется несколько раз. Сделаем 2 элемента 'c' и убедимся в этом:
<?$a=['b','c','c'];foreach($a as$e){if($e=='c'){echo'Есть';/*Выведет несколько раз*/}}?>
Сократим код:
<?$a=['b','c','c'];foreach($a as$e){if($e=='c'){echo'Есть';}}?>
ЕстьЕсть
Исправим проблему: оборвем цикл с помощью break, если элемент уже найден:
<?$a=['b','c','c'];foreach($a as$e){if($e=='c'){echo'Есть';break;/*Оборвем цикл*/}}?>
Сократим код:
<?$a=['b','c','c'];foreach($a as$e){if($e=='c'){echo'Есть';break;}}?>
Есть
Сделаем так, чтобы, если в массиве вообще нет элементов со значением 'c', выводилось 'нет'. Распространенным заблуждением будет добавить else к ифу, в этом случае 'нет' будет выводиться на все элементы, не являющиеся 'c':
<?$a=['b','c','c'];foreach($a as$e){if($e=='c'){echo'Есть';}else{echo'Нет';/*Выведет на 'a','b'*/}}?>
Сократим код:
<?$a=['b','c','c'];foreach($a as$e){if($e=='c'){echo'Есть';}else{echo'Нет';}}?>
НетЕстьЕсть
Идея добавить else - плохая идея, не рабочая. Для решения задач подобного типа используют флаги.
Сделаем переменную $f с таким значением: если она =true, то в массиве есть элемент 'c', а если false, то такого элемента нет.
Изначально поставим переменную $f в значение false, т.е. будем считать, что элемента 'c' в массиве нет:
<?$a=['b','c','c'];$f=false/*Считаем, что элемента 'c' в массиве нет*/?>
Сократим код:
<?$a=['b','c','c'];$f=false?>
Затем запустим цикл с ифом так, как делали это раньше. Если цикл обнаружит, что в массиве есть элемент 'c', то поставим переменную $f в значение true (и выйдем из цикла с помощью break).
<?foreach($a as$e){if($e=='c'){$f=true;/*Элемент есть, переопределим переменную $flag*/break;}}?>
Сократим код:
<?foreach($a as$e){if($e=='c'){$f=true;break;}}?>
Далее: ответ на вопрос, есть в массиве 'c' или нет, можем дать только после цикла. И этот ответ уже есть: после цикла переменная $f могла остаться false или могла сменить свое значение на true, если цикл обнаружил в массиве 'c':
<?$a=['b','c','c'];$f=false;/*Считаем, что элемента 'c' в массиве нет*/foreach($a as$e){if($e=='c'){$f=true;/*Элемент есть, переопределим переменную $f*/break;}}//Тут переменная $f= или true, или false?>
Сократим код:
<?$a=['b','c','c'];$f=false;foreach($a as$e){if($e=='c'){$f=true;break;}}?>
Теперь после цикла можно сделать иф, который посмотрит на переменную $f и выведет на экран 'есть' или 'нет':
<?$a=['b','c','c'];$f=false;/*Считаем, что элемента 'c' в массиве нет*/foreach($a as$e){if($e=='c'){$f=true;/*Элемент есть, переопределим переменную $f*/break;}}if($f===true){echo'Есть';}else{echo'Нет';}?>
Сократим код:
<?$a=['b','c','c'];$f=false;foreach($a as$e){if($e=='c'){$f=true;break;}}if($f===true){echo'Есть';}else{echo'Нет';}?>
Есть
Флаги в функции
Когда мы работаем с пользовательскими функциями, флаги тоже можно и нужно использовать, но работа с ними упрощается. Давайте решим ту же задачу на 'c', но таким образом: необходимо создать функцию q, которая параметром будет принимать массив и возвращать true, если 'c' есть в массиве, и false, если нет:
<?$a=['b','c'];echo q($a)/*Выведет true или false*/?>
Сократим код:
<?$a=['b','c'];echo q($a)?>
1
Реализуем функцию q. В этом случае переменная $f и команда break нам не понадобится, вместо них все сделает команда return.
Как это будет: внутри функции запускается цикл с ифом и, если попали в иф, делаем return true, тем самым выходя из цикла и из функции, а если цикл прокрутился, но выхода из функции не случилось, после цикла делаем return false:
<?function q($a){foreach($a as$e){if($e=='c'){return true;}}return false;/*Элемент 'c' не найден*/}$a=['b','c'];echo q($a)?>
Сократим код:
<?function q($a){foreach($a as$e){if($e=='c'){return true;}}return false;}$a=['b','c'];echo q($a)?>
1
Еще раз как это работает: если в массиве найдется элемент со значением 'c', выйдем из функции с помощью return, но если в массиве не найдется элемент 'c', выхода из функции не произойдет и выполнение дойдет до команды return false и получится, что функция вернет false в знак того, что элемент 'c' не найден в массиве.