ВыраженияОператорыУсловия

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

что в PHP приобретает следующий вид:

$y = 3 * (abs(2*$x) + 4);

Возвращаемое значение (в данном случае y или $y) может быть числом, строкой или булевым (логическим) значением (названным так в честь Джорджа Буля, английского математика и философа XIX века). Первые два типа значений вам уже должны быть знакомы, поэтому я объясню, что такое третий тип.

TRUE или FALSE?

Элементарное булево значение может быть либо истинным — TRUE, либо ложным — FALSE. Например, выражение 20 > 9 (20 больше 9) является истинным (TRUE), а выражение 5 == 6 (5 равно 6) — ложным (FALSE). (Булевы, или логические, операции могут быть объединены путем использования таких операторов, как И, ИЛИ и исключающее ИЛИ, то есть ANDOR и XOR, которые будут рассмотрены в этой главе.)

Обратите внимание, что для имен TRUE и FALSE я использую буквы верхнего регистра. Это обусловлено тем, что в PHP они являются предопределенными константами. При желании можно также применять и их версии, составленные из букв нижнего регистра, поскольку они также являются предопределенными константами. Кстати, версия, в которой задействуются буквы нижнего регистра, более надежна, потому что PHP не допускает ее переопределения, а версия, использующая буквы верхнего регистра, может быть переопределена, и это нужно иметь в виду при импортировании чужого кода.

В примере показаны некоторые простые выражения: два, о которых уже упоминалось, плюс еще два выражения. Для каждой строки выводится буква от a до d, за которой следуют двоеточие и результат выражения (тег <br> используется в HTML для переноса и разбивает выходную информацию на четыре строки).

Теперь, когда HTML5 уже полностью вошел в обиход, и XHTML не планируется на замену HTML, больше уже не нужно использовать самозакрывающуюся форму <br />; тега <br>, или любых пустых элементов (не имеющих закрывающих тегов), поскольку теперь символ / необязателен. Поэтому в данной книге мой выбор пал на использование более простого стиля. Если же где-нибудь сделать непустые теги HTML самозакрывающимися (например, <div />), в HTML5 они не сработают, потому что символ / будет проигнорирован, и их нужно будет, к примеру, заменить структурой <div> ... </div>. Но при работе с XHTML нужно по-прежнему пользоваться формой HTML-синтаксиса <br />.

<?php
  echo "a: [" . (20 > 9) . "]<br>";
  echo "b: [" . (5 == 6) . "]<br>";
  echo "c: [" . (1 == 0) . "]<br>";
  echo "d: [" . (1 == 1) . "]<br>";
?>

Этот код выведет следующую информацию:

<?php
  a: [1]
  b: []
  c: []
  d: [1]
?>

Обратите внимание, что результаты вычисления обоих выражений, a: и d:, являются истинными (TRUE), имеющими значение 1. А результаты вычисления выражений b: и c: ложны (FALSE) и вообще не показывают никакого значения, поскольку в PHP константа FALSE определена как NULL (ничто). Чтобы убедиться в этом, можно ввести код, приведенный в следующем примере:

<?php
  echo "a: [" . TRUE  . "]<br>";
  echo "b: [" . FALSE . "]<br>";
?>

Этот код выведет следующую информацию:

a: [1]
b: []

Кстати, в некоторых языках константа FALSE может быть определена как 0 или даже как –1, поэтому в каждом языке ее определение стоит проверить.

Литералы и переменные

Простейшей формой выражения является литерал, означающий нечто, вычисляющееся само в себя, например число 73 или строка Hello. Выражение может также быть просто переменной, которая вычисляется в присвоенное этой переменной значение. Обе формы относятся к типам выражений, поскольку они возвращают
значение.

В примере показаны три литерала и две переменные, все они возвращают значения, хотя и разных типов.

<?php
  $myname = "Brian";
  $myage = 37;
  echo "a: " . 73      . "<br>"; // Числовой литерал
  echo "b: " . "Hello" . "<br>"; // Строковый литерал
  echo "c: " . FALSE   . "<br>"; // Литерал константы
  echo "d: " . $myname . "<br>"; // Строковая переменная
  echo "e: " . $myage  . "<br>"; // Числовая переменная
?>

Как и ожидалось, в выходной информации вы увидите возвращаемое значение всех этих выражений, за исключением выражения c:, результат вычисления которого является FALSE и ничего не возвращает:

a: 73
b: Hello
c:
d: Brian
e: 37

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

В первой из них осуществляется присваивание результата выражения 366 - $day_number переменной $days_to_new_year, а во второй выводится приветственное сообщение, если выражение $days_to_new_year < 30 вычисляется как TRUE.

<?php
  $days_to_new_year = 366 - $day_number;  // Выражение
  if ($days_to_new_year < 30)
  {
    echo "Скоро Новый год!";      // Инструкция
  }
?>

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

ОператорОписаниеПример
АрифметическийЭлементарная математика$a + $b
Для работы с массивомСлияние массивов$a + $b
ПрисваиванияПрисваивание значений$a = $b + 23
ПоразрядныйМанипуляция битами в байте12 ^ 9
СравненияСравнение двух значений$a < $b
ВыполненияВыполнение содержимого, заключенного в обратные кавычки`ls -al`
Инкремента/декрементаДобавление или вычитание единицы$a++
ЛогическийВыполнение булевых сравнений$a and $b
СтроковыйОбъединение строк$a . $b

Различные типы операторов воспринимают разное количество операндов.

  • Унарные операторы, такие как оператор инкремента ($a++) или изменения знака числа (-$a), воспринимают только один операнд.
  • Бинарные операторы, представленные большим количеством операторов PHP, включая операторы сложения, вычитания, умножения и деления, воспринимают два операнда.
  • Один трехкомпонентный оператор, имеющий форму x ? y : z. По сути, это состоящая из трех частей однострочная инструкция if, в которой осуществляется выбор между двумя выражениями, зависящий от результата вычисления третьего выражения.

Приоритетность операторов

Если бы у всех операторов был один и тот же уровень приоритета, то они обрабатывались бы в том порядке, в котором встречались интерпретатору. Фактически многие операторы имеют одинаковый уровень приоритета, что и показано здесь:

1 + 2 + 3 - 4 + 5
2 - 4 + 5 + 3 + 1
5 + 2 - 4 + 1 + 3

Из примера видно, что, несмотря на перестановку чисел (и предшествующих им операторов), результат каждого выражения имеет значение 7, поскольку у операторов «плюс» и «минус» одинаковый уровень приоритета. Можно проделать то же самое с операторами умножения и деления, что показано чуть ниже.

1 * 2 * 3 / 4 * 5
2 / 4 * 5 * 3 * 1
5 * 2 / 4 * 1 * 3

В этом примере получаемое значение всегда равно 7,5. Но все меняется, когда в выражении присутствуют операторы с разными уровнями приоритета. Вот три выражения, в которых присутствуют операторы с разными уровнями приоритета:

1 + 2 * 3 - 4 * 5
2 - 4 * 5 * 3 + 1
5 + 2 - 4 + 1 * 3

Если бы не существовало приоритетности операторов, то в результате вычисления этих выражений получались бы числа 25–29 и 12 соответственно. Но поскольку операторы умножения и деления имеют более высокий уровень приоритета по сравнению с операторами сложения и вычитания, вокруг частей выражения с их участием предполагается наличие скобок, и если их сделать видимыми, выражения будут выглядеть так, как в трёх выражениях, в которых отображены предполагаемые скобки

1 + (2 * 3) - (4 * 5)
2 - (4 * 5 * 3) + 1
5 + 2 - 4 + (1 * 3)

Очевидно, что PHP должен сначала вычислить подвыражения, заключенные в скобки, чтобы получились частичные вычисленные, показанные в выражениях после вычисления подвыражений в скобках

1 + (6) - (20)
2 - (60) + 1
5 + 2 - 4 + (3)

Окончательный результат вычисления этих выражений равен соответственно –13–57 и 6 (что абсолютно отличается от результатов 25–29 и 12, которые мы увидели бы при отсутствии приоритетности операторов). Разумеется, исходную приоритетность операторов можно отменить, расставив собственные скобки, и принудительно получить результаты, показанные в самом начале, которые были бы получены в отсутствие приоритетности операторов:

((1 + 2) * 3 - 4) * 5
(2 - 4) * 5 * 3 + 1
(5 + 2 - 4 + 1) * 3

Теперь, если скобки расставлены правильно, мы увидим значения 25–29 и 12 соответственно. В таблице перечислены операторы в порядке их приоритетности от самого высокого до самого низкого уровня.

Таблица: Операторы PHP, расположенные по уровню их приоритетности (сверху вниз)

ОператорТип
()Скобки
++ ––Инкремент/декремент
!Логический
* / %Арифметические
+ —Арифметические и строковые
<< >>Побитовые
< <= > >= <>Сравнения
== != === !==Сравнения
&Поразрядный (и ссылочный)
^Поразрядный
|Поразрядный
&&Логический
||Логический
? :Трехкомпонентный
= += –= *= /= .= %= &= != ^= <<= >>=Присваивания
andЛогический
xorЛогический
orЛогический

Взаимосвязанность операторов

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

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

Рассмотрим оператор присваивания, показанный в примере, где всем трем переменным присваивается значение 0.

<?php
$level = $score = $time = 0;
?>

Такое множественное присваивание возможно только в том случае, если сначала вычисляется самая правая часть выражения, а затем процесс продолжается справа налево.

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

Операторы отношения

Операторы отношения проверяют значения двух операндов и возвращают логический результат, равный либо TRUE, либо FALSE. Существует три типа операторов отношения: операторы равенства, сравнения и логические операторы.

Операторы равенства

С оператором равенства == (двойным знаком равенства) мы уже не раз встречались в этой книге. Его не следует путать с оператором присваивания = (одинарным знаком равенства). В примере ниже первый оператор присваивает значение, а второй проверяет его на равенство:

<?php
$month = "Март";
if ($month == "Март") echo "Весна наступила";
?>

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

К примеру, любые строки, составленные полностью из цифр, при сравнении с числами будут преобразованы в числа. В примере ниже переменные $a и $b являются двумя разными строками, и поэтому вряд ли стоило ожидать, что какая-то из инструкций if выведет результат.

<?php
$a = "1000";
$b = "+1000";
if ($a == $b) echo "1";
if ($a === $b) echo "2";
?>

Но если запустить этот пример, то он выведет число. Это означает, что результат вычисления первой инструкции if является TRUE. Причина в том, что обе строки сначала конвертируются в числа, и 1000 имеет такое же числовое значение, что и +1000.

В отличие от первой, во второй инструкции if используется оператор тождественности — тройной знак равенства, который удерживает PHP от автоматического преобразования типов. Поэтому переменные $a и $b сравниваются как строки и теперь считаются отличающимися друг от друга, и на экран ничего не выводится. Как и в случае с принудительным заданием уровня приоритетности операторов, если возникнут сомнения в том, будет ли PHP конвертировать типы операндов, для отмены такого поведения интерпретатора можно воспользоваться оператором тождественности.

Аналогично применению оператора равенства для определения равенства операндов можно проверить их на неравенство, используя оператор неравенства !=. В примере ниже операторы равенства и тождественности были заменены противоположными им операторами.

<?php
$a = "1000";
$b = "+1000";
if ($a != $b) echo "1";
if ($a !== $b) echo "2";
?>

Как, наверное, и ожидалось, первая инструкция if не выводит на экран число 1, потому что в коде ставится вопрос о неравенстве числовых значений переменных $a и $b. Вместо этого будет выведено число 2, поскольку вторая инструкция if ставит вопрос о нетождественности прежнего типа операндов переменных $a и $b, и ответом будет TRUE, потому что они не тождественны.

Операторы сравнения

Используя операторы сравнения, можно расширить круг проверок, не ограничивая его только равенством и неравенством. PHP предоставляет вам для этого операторы > (больше), < (меньше), >= (больше или равно) и <= (меньше или равно). Здесь показано использование этих операторов.

<?php
  $a = 2; $b = 3;
  if ($a > $b)  echo "$a больше $b<br>";
  if ($a < $b)  echo "$a меньше $b<br>";
  if ($a >= $b) echo "$a больше или равно $b<br>";
  if ($a <= $b) echo "$a меньше или равно $b<br>";
?>

Этот пример, в котором переменная $a имеет значение 2, а переменная $b — значение 3, выведет на экран следующую информацию:

2 меньше 3

2 меньше или равно 3

Попробуйте самостоятельно запустить этот пример, меняя значения переменных $a и $b, чтобы увидеть результаты. Присвойте им одинаковые значения и посмотрите, что из этого получится.

Логические операторы

Логические операторы выдают истинные или ложные результаты. Всего имеется четыре таких оператора

Таблица: Логические операторы

Логический операторОписание
ANDВозвращает истинное значение (TRUE), если оба операнда имеют истинные значения
ORВозвращает истинное значение (TRUE), если любой из операндов имеет истинное значение
XORВозвращает истинное значение (TRUE), если один из двух операндов имеет истинное значение
NOTВозвращает истинное значение (TRUE), если операнд имеет ложное значение, или ложное значение (FALSE), если он имеет истинное значение

Использование этих операторов показано в примере ниже. Обратите внимание, что PHP требует использовать вместо слова NOT символ !. Кроме того, операторы могут быть составлены из букв нижнего или верхнего регистра.

<?php
  $a = 1; $b = 0;
  echo ($a AND $b) . "<br>";
  echo ($a or $b)  . "<br>";
  echo ($a XOR $b) . "<br>";
  echo !$a         . "<br>";
?>

Этот пример выводит на экран NULL, 1, 1, NULL. Это значит, что только вторая и третья инструкции echo получают в результате вычисления значение TRUE. (Следует помнить, что NULL, или ничто, отображает значение FALSE.) Такой результат получается, потому что оператору AND, чтобы вернуть значение TRUE, нужно, чтобы оба операнда имели истинное значение, а четвертый оператор проводит над значением переменной $a операцию NOT, превращая его из TRUE (значения, равного единице) в FALSE. Если есть желание поэкспериментировать, запустите этот код, присваивая переменным $a и $b разные значения, выбранные из 1 и 0.

Занимаясь программированием, следует помнить, что у операторов AND и OR более низкий уровень приоритета, чем у других версий этих операторов — && и ||. Поэтому в сложных выражениях более безопасным будет, наверное, применение операторов && и ||.

Использование в инструкции if оператора OR может стать причиной непредвиденных проблем, поскольку второй операнд не будет вычисляться, если в результате вычисления первого операнда уже получено значение TRUE. В примере функция getnext никогда не будет вызвана, если переменная $finished имеет значение 1.

<?php
if ($finished == 1 OR getnext() == 1) exit;
?>

Если нужно, чтобы функция getnext вызывалась для каждой инструкции if, следует внести в код изменения, показанные в примере изменения в инструкции if … OR, гарантирующие вызов функции getnext

<?php
$gn = getnext();
if ($finished == 1 OR $gn == 1) exit;
?>

В этом случае код в функции getnext будет выполнен и возвращенное значение сохранится в переменной $gn еще до выполнения инструкции if. Другое решение заключается в том, чтобы обеспечить выполнение функции getnext за счет простой перестановки условий местами, поскольку тогда вызов функции будет появляться в выражении первым.

В таблице ниже показаны все допустимые варианты использования логических операторов. Следует заметить, что !TRUE является эквивалентом FALSE, а !FALSE — эквивалентом TRUE.