§4. Управляющие конструкции

4.1. Подробнее об инструкциях.

Прежде, чем приступить к описанию основных управляющих конструкций языка PHP, давайте еще раз сформулируем само понятие инструкции.

Инструкция – это команда на языке PHP, которая выполняется для того, чтобы что-то происходило. По сути, любой php-скрипт представляет собой не что иное, как некоторую последовательность инструкций.

К инструкции можно отнести присваивание, сравнение, вызов функции, различные циклы и условные операторы или даже пустой оператор, т.е. пустую инструкцию, которая ничего не делает. Как уже было показано выше, в PHP каждая инструкция отделяется от других точкой с запятой ';', которая обычно ставится в той же строке в конце каждой инструкции. Если инструкция является последней в блоке php-кода, то после нее точку с запятой разрешается не ставить, т.к. закрывающий тег сделает это автоматически. Кроме того, инструкции могут быть объединены посредством фигурных скобок в целые блоки инструкций, каждый из которых сам по себе является отдельной составной инструкцией.

По умолчанию интерпретатор PHP выполняет инструкции последовательно одна за другой в порядке их следования в коде. Однако имеется и ряд специальных инструкций, называемых управляющими конструкциями, которые изменяют выполнение хода программы по умолчанию. К ним относятся:

В данном параграфе мы как раз и будем заниматься рассмотрением различных управляющих конструкций, использующихся в языке PHP.

4.2. Условный оператор if.

Если говорить в общем, то условные операторы позволяют пропустить или выполнить некоторый блок кода в зависимости от результата вычисления своего условного выражения (условия). Простейшим из условных операторов является оператор if, который вычисляет значение своего условного выражения, преобразуя его по необходимости в булев тип, и по результатам вычисления принимает решение – если конечный результат имеет значение true, то интерпретатор выполняет указанный фрагмент кода, а если конечный результат имеет значение false, то интерпретатор пропускает данный фрагмент кода и начинает выполнять следующую за условным оператором инструкцию. Использование условного оператора if показано в примере 4.1.

<?php
$a=5; 	//Присвоили переменной число

if($a>0){//В круглых скобках записывается условие оператора if
$a=++$a; //Код, который выполняется в случае истинности условия
			//заключается в фигурные скобки, т.е. в тело оператора
}			//Точку с запятой после фигурных скобок не ставят

echo $a; //Выведет 6, т.к. условие оператора if оказалось истинным,
			//поэтому инструкция в теле оператора, т.е. между
			//открывающей и закрывающей фигурными скобками, была выполнена, 
			//Если бы условие оказалось ложным, то весь код в теле 
			//оператора if был бы пропущен и оператор echo вывел бы 5
?>

Пример 4.1. Условный оператор if и его синтаксис

Отметим, что в теле оператора if может содержаться произвольное число инструкций, выполняемых условно. Так что нет необходимости для каждой из инструкций использовать отдельный оператор if. Кроме того, в теле оператора if разрешается использовать как другие вложенные операторы if, так и вложенные управляющие конструкции других видов, что значительно повышает возможности организации условного выполнения различных частей программы.

Если в зависимости от результата проверки условного выражения нужно выполнить одну из двух инструкций, то оператор if расширяется при помощи оператора else, который в случае, если значение условия равно false, позволяет выполнить альтернативную инструкцию (см. пример 4.2).

<?php
$a=5;		//Присвоили переменной число

if($a<0){// В круглых скобках записывается условие оператора if
$a=++$a; //Код, который выполняется в случае истинности условия,
			//заключается в фигурные скобки до ключевого слова else
}else{   //Код, который выполняется в случае ложности условия,
			//заключается в фигурные скобки после ключевого слова else
$a=--$a;	
}        //Точку с запятой после фигурных скобок не ставят

echo $a; //Выведет 4, т.к. условие оператора if оказалось ложным,
			//поэтому была выполнена вторая инструкция 
?>

Пример 4.2. Расширение оператора if при помощи ключевого слова else

Более того, если значение условия оператора if окажется ложным, имеется возможность не просто выполнить альтернативную инструкцию, а выбрать ее из нескольких подходящих вариантов. Для этого оператор if расширяется при помощи оператора elseif, который по сути служит для объединения двух соседних операторов if (см. пример 4.3).

<?php
$a=5; 				//Присвоили переменной число

if($a<0){ 			// В круглых скобках записывается условие оператора if
$a=-1; 				//Код, который выполняется в случае истинности условия
}elseif($a==0){   
$a=0;					//Выполняется в случае ложности предыдущего условия
}elseif($a>0&&$a<=5){   
$a=1;       		//Выполняется в случае ложности всех предыдущих условий
}else{   
$a=++$a;       	//Выполняется в случае ложности всех предыдущих условий
}						//Точку с запятой после фигурных скобок не ставят

echo $a; 			//Выведет 1, т.к. первым истинным условием является $a>0&&$a<=5
?>

Пример 4.3. Расширение оператора if при помощи ключевого слова elseif

Как видно из примера, можно применять сразу несколько операторов elseif. При этом, в отличие от оператора else, при использовании оператора elseif выполнение альтернативного выражения произойдет только тогда, когда его условие будет иметь значение true, а условные выражения всех предыдущих аналогичных операторов будут иметь значения, равные false.

Ключевые слова else и if разрешается писать отдельно в формате языка JavaScript, т.е. в виде else if. Однако следует помнить, что при использовании альтернативного синтаксиса с применением двоеточия так делать нельзя. Но, поскольку мы не будем ни рассматривать, ни пользоваться альтернативным синтаксисом – оба варианта можно считать равнозначными.

4.3. Условный оператор switch.

Оператор switch по своему действию похож на серию последовательных операторов if с одинаковым условием. Он применяется в тех случаях, когда требуется сравнить одну и ту же переменную или выражение с множеством различных значений и в зависимости от результата сравнения выполнить различные участки кода. Использование оператора switch показано в примере 4.4.

<?php
$a=5; 				//Присвоили переменной число

switch($a){ 		//В круглых скобках записывается условие оператора switch
	case 5:   		//Оператор case служит меткой для указания места, с которого 
						//интерпретатор будет выполнять код, если его значение 
						//окажется равным значению условия оператора switch
		echo '$a равно 5';.'<br>'  //Выведет эту строку, т.к. $a==5
		break;  		//Оператор break прерывает выполнение всей текущей конструкции
	case 0:
		echo '$a равно 0';		   //Выполняться не будет, т.к. $a<>0
		break;
	case 8:
		echo '$a равно 8'; 		   //Выполняться не будет, т.к. $a<>8
		break;
	default: //Оператор default служит меткой для указания места, с которого 
	 			//интерпретатор будет выполнять код, если не сработает ни один из 
				//операторов case  
		echo 'Совпадений не обнаружено.';	
}				//Точку с запятой после фигурных скобок не ставят

/* Тоже самое можно проделать при помощи серии операторов if и else/if */

if($a==5){ 		
	echo '$a равно 5'.'<br>';		 //Выведет эту строку, т.к. $a==5
}else if($a==0){	
		echo '$a равно 0';  
}else if($a==8){	
		echo '$a равно 8';  
}else{			
		echo 'Совпадений не обнаружено.';	
}				
?>

Пример 4.4. Условный оператор switch

Также, как и в случае с оператором if, в круглых скобках после ключевого слова switch записывается условие оператора, после чего в фигурных скобках располагается и само тело оператора. В теле оператора записывают необходимое количество специальных меток, сформированных из операторов case, соответствующих им выражений, которые могут быть приведены к простому типу, например, integer, float, bool, string, и двоеточий, завершающих конструкции меток. После меток записываются соответствующие данным меткам фрагменты кода, которые будут выполнены в случае равенства значения условия оператора switch значению выражения данной метки.

Поскольку в операторе switch выражение вычисляется всего один раз и этот результат сравнивается со значением каждого оператора case, а условие оператора elseif вычисляется снова в каждом из них, то в случае сложных сравнений или нахождения внутри цикла конструкция switch может работать быстрее, чем соответствующая конструкция if с дополнительными операторами elseif.

Отметим, что после вычисления значения условия оператора switch интерпретатор начинает сравнивать это значение со значениями операторов case. При этом используется нестрогое сравнение при помощи оператора '=='. Когда совпадение будет найдено, интерпретатор начинает выполнять весь последующий код вплоть до конца блока switch, т.е. включая код всех последующих операторов case и необязательного оператора default (см. пример 4.5). Поэтому, во избежание такого поведения интерпретатора, следует в конце соответствующих кусков кода применять оператор break, который служит для прерывания текущего оператора switch и передачи управления оператору, следующему за ним.

<?php
$a="Фрукты"; 			//Присвоили переменной строку

switch($a){ 		
	case "Овощи":   		 
		echo 'Морковь';//Выполняться не будет, т.к. $a<>"Фрукты"
	case "Фрукты": 	//Отсюда и до конца блока switch все инструкции будут выполнены
		echo 'Яблоки'.'<br>';					 //Строка будет выведена 
	case "Ягоды":
		echo 'Черника'.'<br>';					 //Строка будет выведена 
	default: 
		echo 'Фрукты отсутствуют.'.'<br>';	 //Строка будет выведена 
}			
?>

Пример 4.5. Выполнение оператора switch в случае отсутствия операторов break

Что касается применения необязательного оператора default, то он используется в случае, когда необходимо выполнить какой-нибудь альтернативный код при отсутствии каких-либо совпадений результата условия оператора switch со значениями имеющихся операторов case.

Если один и тот же код должен быть исполнен для различных значений условия оператора switch, то соответствующие этим значениям операторы case можно оставить пустыми, за исключением последнего в списке, в котором и следует записать код для исполнения (см. пример 4.6).

<?php
$a="Спорт"; 	//Присвоили переменной строку

switch($a){ 		
	case "Курение":   		 
		echo 'Вредит здоровью';			//Не выведется, т.к. $a<>"Спорт"
	case "Спорт": 	
	case "Здоровый сон":
	case "Правильное питание":	
		echo 'Полезно для здоровья.'; //Данная строка будет выведена при 
		      //равенстве условия оператора switch одному из трех вариантов
}			
?>

Пример 4.6. Применение пустых операторов case

4.4. Циклы while и do/while.

Представителем простейшего вида циклов в PHP является цикл while, который служит для повторного выполнения кода, расположенного в его теле, до тех пор, пока условие цикла остается истинным, т.е. имеет значение true (см. пример 4.7).

<?php
$a=6; //Присвоили переменной стартовое значение 

while($a<=10){ 		
	echo $a=++$a; //Код выполняется пока $a<=10
}		
	/* Выведет в ходе цикла 7891011 */
?>

Пример 4.7. Цикл while

Как видно из примера, условие цикла записывается в круглых скобках после ключевого слова while, затем в фигурных скобках записывается блок инструкций для исполнения. Работает цикл while следующим образом: каждый раз перед выполнением новой итерации, т.е. очередного выполнения блока инструкций в теле цикла, происходит проверка его условия и, если результат будет иметь значение true, код в теле цикла выполняется; далее интерпретатор возвращается в начало цикла и снова проверяет его условие, повторяя все процедуры заново до тех пор, пока условие цикла не вернет значение false; в этом случае интерпретатор прерывает выполнение цикла и, пропустив блок инструкций в его теле, передает управление следующему за циклом оператору.

Цикл do/while очень похож на цикл while, но в нем истинность выражения проверяется не в начале итерации, а в конце (см. пример 4.8).

<?php
$a=6; //Присвоили переменной стартовое значение 

do{ 		
	echo $a=++$a; 	//Код выполняется пока $a<=10
}while($a<=10);	//Условие цикла проверяется в конце после тела 	

/* Выведет в ходе цикла 7891011, как и в случае
 цикла while в предыдущем примере */
 
	/* После закрывающей круглой скобки условия не забываем ставить 
	точку с запятой!!! Напомним, что опускать ее можно только, если 
	инструкция является последней в блоке php-кода */
?>

Пример 4.8. Цикл do/while

Как видно из примера, в цикле do/while сперва идет ключевое слово do, затем следует тело цикла и только в самом конце записывается ключевое слово while с условием цикла, содержащегося в круглых скобках после него. Как следствие, первая итерация цикла do/while гарантированно выполнится хотя бы раз, в то время как обычный цикл while может быть прерван сразу же после первой проверки условия, если его значение изначально окажется ложным (см. пример 4.9).

<?php
$a=11;		     //Присвоили переменной стартовое значение 

while($a<=10){ 		
	echo $a=++$a; //Код не выполнится вообще ни разу, т.к. изначально $a>10
}	

do{ 		
	echo $a=++$a; //Веведет 12
}while($a<=10);  //После первой же проверки условия цикл будет прерван
?>

Пример 4.9. Отличие цикла while от цикла do/while

После закрывающей круглой скобки условия цикла do/while нужно обязательно ставить точку с запятой. Опускать ее разрешается только в случае, когда инструкция является последней в блоке php-кода.

4.5. Цикл for.

Еще одним циклом в PHP является цикл for. Прежде, чем описать его синтаксис давайте рассмотрим пример 4.10.

<?php
$a=3; 					//Присвоили переменной стартовое значение 

for($i=1;$i<5;$i++){ //Выражения в условии отделяются точками с запятой		
	echo $a=++$a; 		//Код в теле цикла выполняется в случае истинности 
							//второго выражения в условии цикла
}	

/* Первое выражение в условии цикла вычисляется только один раз в самом начале 
цикла, а его результат представляет собой некоторое стартовое значение */

/* Второе выражение является условным: если оно принимает значение true, то 
цикл продолжается, и код в теле цикла будет выполнен;  если же оно принимает 
значение false, выполнение цикла заканчивается */

/* Третье выражение вычисляется в конце каждой итерации перед началом 
следующей проверки второго (условного) выражения */
?>

Пример 4.10. Цикл for

Итак, сперва записывается ключевое слово for, затем в круглых скобках через точку с запятой записываются три выражения (условие цикла), после чего фигурными скобками формируется тело цикла, в котором находится выполняемый циклом код. Первое выражение в условии вычисляется только один раз в самом начале цикла, а его результат представляет собой некоторое стартовое значение, например, счетчика цикла. Второе выражение является условным: если оно принимает значение true, то цикл продолжается, и код в теле цикла будет выполнен; если же оно принимает значение false, то выполнение цикла прерывается. Третье выражение вычисляется в конце каждой итерации перед началом следующей проверки второго (условного) выражения и обычно увеличивает стартовое значение цикла на единицу.

Отметим, что каждое из выражений условия цикла может быть пустым или содержать несколько выражений, разделенных запятыми. Несколько выражений могут понадобиться, например, если используется более одного счетчика цикла. Однако следует иметь в виду, что условные выражения во второй части условия цикла, хоть и вычисляются все, – результат используется только последнего из них. Кроме того, если условное выражение вообще отсутствует, то интерпретатор неявно воспринимает это значение как true, и цикл будет выполняться бесконечно. Данный прием может быть полезен, когда необходимо прервать цикл в нужный момент, используя оператор break. Чтобы было понятнее, давайте рассмотрим пример 4.11.

<?php
for($i=1; $i<=5; $i++){ 	
	echo $i;		 //За цикл выведет 12345
}	

echo '<br>';

for ($i=1; ;$i++) {
    if ($i>5) {
        break;  //Иначе цикл будет бесконечным
    }
    echo $i; 	 //За цикл также выведет 12345
}

echo '<br>';

for($i=1,$k=1; $i<=3; $i++,$k*=5){ 	
	echo $i.' '.$k.' '; //За цикл выведет 1 1 2 5 3 25
}	
?>

Пример 4.11. Использование цикла for

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

4.6. Цикл foreach.

Несмотря на универсальность применения цикла for, который позволяет сымитировать поведение практически любой управляющей конструкции языка PHP, для последовательного перебора элементов массива используется специально созданный для этого оператор цикла foreach, для которого предусмотрены два варианта синтаксиса (см. пример 4.12).

<?php
$arr=["one"=>1,"two"=>2,3,4,5]; //Создали массив с 5 элементами

foreach($arr as $value){ 		  //Первый вариант цикла
	echo $value." ";  			  //Выведет в ходе цикла все значения элементов массива
}	

echo '<br>';

foreach($arr as $key=>$value){  //Второй вариант цикла
	echo $key."=>".$value." ";   //Выведет в ходе цикла все пары 
										  //'ключ=>значение' элементов массива
}

/* Как видим, второй вариант позволяет дополнительно перечислить и 
использовать не только значения элементов массива, но и ключи массива. */ 
?>

Пример 4.12. Цикл foreach

Как видно из примеров, для организации цикла foreach в первом случае указывается ключевое слово foreach; затем в круглых скобках записывается условие цикла, состоящее из имени массива $array, элементы которого будут последовательно перечисляться, ключевого слова as и имени переменной $value, которой при каждой новой итерации цикла будут присваиваться соответствующие значения элементов массива; после условия при помощи фигурных скобок записывается тело цикла. Во втором случае в условие цикла добавляется еще одна переменная $key, которой при каждой новой итерации цикла будут присваиваться строки с именами ключей перечисляемых в цикле значений элементов массива. Понятно, что имена для переменных $key и $value могут быт выбраны произвольно.

Оператор цикла foreach очень удобен в использовании, поскольку он никогда не выходит за пределы массива, а также сам выполняет обход и чтение всех элементов массива до тех пор, пока не будет достигнут последний из них.

Если возникает необходимость изменения элементов массива при помощи оператора цикла foreach, то значения переменной $value следует передавать по ссылке используя перед ней символ '&' (см. пример 4.13).

<?php
$arr=[1,2,3,4];//Создали массив с 4 элементами

foreach($arr as &$value){ //Работаем со значениями массива по ссылке 
	$value*=2;	//Увеличиваем каждый элемент массива в два раза
	echo $value." ";  	  //Выведет в ходе цикла 2 4 6 8
}	

echo '<br>';

unset($value); //Разрываем ссылку на последний элемент, ведь если мы случайно 
					//изменим значение переменной $value, то изменится и последний 
					//элемент массива
echo $arr[0];  //Выведет 2, т.е. элементы массива благодаря циклу изменились

/* При использовании значений по ссылке массив должен быть присвоен переменной,
поэтому запись вида foreach([1,2,3,4] as &$value)... недопустима */
?>

Пример 4.13. Изменение элементов массива с помощью цикла foreach

Следует помнить, что ссылка на последний элемент массива остается даже после того, как оператор foreach завершил работу. Поэтому рекомендуется удалять ее с помощью функции unset() во избежание нежелательных последствий, связанных со случайным присвоением переменной нового значения и, как следствие, изменения последнего элемента массива. Кроме того, перебор элементов массива по ссылке возможен только, если перебираемый массив является переменной.

4.7. Операторы break, continue и goto.

Как было показано выше, иногда может возникать необходимость в досрочном прекращении цикла. Для этого случая в PHP предусмотрен специальный оператор break, который широко используется не только во всех перечисленных циклах, но и в условном операторе switch. Более того, данный оператор может принимать необязательный числовой аргумент, который указывает интерпретатору на количество вложенных структур, которые необходимо прервать (см рис. 4.14).

<?php
$k=0; 	//Задаем стартовое значение переменной

for($i=1; $i<=7; $i++){ //Внешний цикл
	while($k<9){			//Внутренний цикл
		$k+=1;				//Увеличиваем значение на единицу
		if($k==4){			//При достижении значения $k==4
			break 2;			//прерываются оба цикла сразу
		}
	}
}	
/* Благодаря прерыванию сразу обоих циклов внешний цикл 
прервется уже в ходе выполнения первой итерации */
echo $k; //Выведет 4
?>

Пример 4.14. Использование оператора break

Если бы в примере отсутствовал числовой аргумент 2 оператора break, то при достижении переменной $k значения 4 прервался бы только внутренний цикл. В результате внешний цикл смог бы продолжить свою работу, и в конечном итоге переменная $k достигла бы значения 9. Измените код примера и посмотрите, как изменится результат.

Когда нужно прервать не цикл, а только его текущую итерацию, используется оператор continue. Он также, как и оператор break, используется в циклах и операторе switch и может принимать необязательный числовой аргумент, указывающий интерпретатору на количество вложенных структур, текущие итерации которых требуется прервать (см. пример 4.15).

<?php
$k=0; 				//Задаем стартовое значение переменной

for($i=1; $i<=7; $i++){ //Внешний цикл
	while($k<9){			//Внутренний цикл
		$k+=1;				//Увеличиваем значение на единицу
		if($k==4){			//При достижении значения $k==4
			continue 2;		//прерываются текущие итерации обоих циклов сразу
		}
		echo $k; 	//Из-за continue не будет выведено значение $k==4
	}
	echo $i;   		//Из-за continue не будет выведено значение $i==1
}	
?>

Пример 4.15. Использование оператора continue

Выйти из цикла можно также при помощи оператора goto, который используется для перехода в другую часть программы, помеченную специальной меткой в виде идентификатора и следующего за ним двоеточия (см. пример 4.16).

<?php
for($i=1; $i<=7; $i++){ 
	echo $i; 	 //Из-за goto эта инструкция выполнится только один раз,  
					 //после чего интерпретатор перейдет к метке var_1 
	
	goto var_1;  //Переходим к указанной метке, пропуская промежуточный код 
	++$i; 		 //Из-за goto эта инструкция не выполнится ни разу
}
var_1:	       //Задаем метку для перехода при помощи оператора goto
echo '<br>'.'Сюда я перехожу из цикла';   

goto var_2;     //Переходим к следующей метке, пропуская промежуточный код
echo 'Я выведен не буду'; 					 //Этот код будет пропущен

var_2:	   	 //Задаем еще одну метку для перехода при помощи оператора goto
echo '<br>'.'А вот меня покажут всем';  //Этот код будет выполнен
?>

Пример 4.16. Использование оператора goto

Целевая метка должна находиться в том же файле и в том же контексте, что и оператор goto, указывающий на нее. Это означает, что нельзя переходить изнутри функции (метода) наружу или совершать обратный переход. Также недопустим переход извне внутрь любой циклической структуры или оператора switch.

Таким образом, основным предназначением оператора goto следует считать использование его в циклических структурах вместо многоуровневых операторов break.

Контрольные вопросы и задания

  1. Что такое инструкция? Какие инструкции называют сложными?
  2. Перечислите виды управляющих конструкций PHP.
  3. Опишите условный оператор if. Разрешается ли использование вложенных операторов if?
  4. Каков синтаксис использования оператора elseif?
  5. Опишите условный оператор switch. Какой из операторов работает быстрее: if или switch?
  6. Значения какого типа может принимать оператор case в качестве своего аргумента? Для чего в конструкции switch используются операторы break и default?
  7. Опишите циклы while и do/while. В чем заключается их основное различие?
  8. Опишите оператор цикла for.
  9. Опишите оператор цикла foreach. В чем заключается его преимущество перед циклом for при использовании с массивами?
  10. Опишите порядок использования операторов break, continue и goto.

Словарь новых английских слов

if [if] – если.
else [els] – иначе, еще.
switch [swɪtʃ] – переключение.       
case [keɪs] – блок, контейнер.
break [breɪk] – прерывать.
while [wʌɪl] – до тех пор пока.
do [duː] – делать.
for [fɔː] – для.
each [iːtʃ] – каждый.
continue [kənˈtɪnjuː] – продолжать.
default [dɪˈfɔːlt] – по умолчанию.
key [kiː] – ключ.
as [æz] – как.
value [ˈvaljuː] – значение.

 

belarusweb.net   ©  Петр Романовский, Минск, 2016.