Глава 14. Выражения

Выражения - это краеугольный камень PHP. Почти все, что вы пишите в PHP, является выражением. Самое простое и точное определение выражения - "все что угодно, имеющее значение".

Основными формами выражений являются константы и переменные. Если вы записываете "$a = 5", вы присваиваете '5' переменной $a. '5', очевидно, имеет значение 5 или, другими словами, '5' это выражение со значением 5 (в данном случае '5' это целочисленная константа).

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

Немного более сложными примерами выражений являются функции. Например, рассмотрим следующую функцию:

<?php
function foo ()
{
    return
5;
}
?>

Исходя из того, что вы хорошо знакомы с концепцией функций (если нет, то прочитайте главу о функциях), вы полагаете, что запись $c = foo() абсолютно эквивалента записи $c = 5, и вы правы. Функции - это выражения, значением которых является то, что возвращает функция. Поскольку foo() возвращает 5, значением выражения 'foo()' является 5. Как правило, функции возвращают не просто статическое значение, а что-то вычисляют.

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

До сих пор пользователи PHP/FI 2 не должны были почувствовать каких-либо изменений. Однако PHP, как и многие другие языки, понимает гораздо больше выражений. PHP - это язык, ориентированный на выражения и рассматривающий почти все как выражение. Вернемся к примеру, с которым мы уже имели дело: '$a = 5'. Легко заметить, что здесь присутствуют два значения - значение целочисленной константы '5' и значение переменной $a, также принимающей значение 5. Но на самом деле здесь присутствует и еще одно значение - значение самого присвоения. Само присвоение вычисляется в присвоенное значение, в данном случае - в 5. На практике это означает, что '$a = 5', независимо от того, что оно делает, является выражением со значением 5. Таким образом, запись '$b = ($a = 5)' равносильна записи '$a = 5; $b = 5;' (точка с запятой обозначает конец выражения). Поскольку операции присвоения анализируются справа налево, вы также можете написать '$b = $a = 5'.

Другой хороший пример ориентированности на выражения - пре- и постфиксный инкремент и декремент. Пользователи PHP/FI 2 и многих других языков возможно уже знакомы с формой записи переменная++ и переменная--. Это операторы инкремента и декремента. В PHP/FI 2 операция '$a++' не имеет значения (это не выражение), и, таким образом, вы не можете присвоить ее или каким-либо образом использовать. PHP увеличивает возможности инкремента/декремента, также сделав их выражениями, как в C. Также как и C, PHP поддерживает два типа инкремента - префиксный и постфиксный. Они оба инкрементируют значение переменной и эффект их действия на нее одинаков. Разница состоит в значении выражения инкремента. Префиксный инкремент, записываемый как '++$variable', вычисляется в инкрементированное значение (PHP инкрементирует переменную перед тем как прочесть ее значение, отсюда название 'пре-инкремент'). Постфиксный инкремент, записываемый как '$variable++', вычисляется в первоначальное значение переменной $variable перед ее приращением (PHP инкрементирует переменную после прочтения ее значения, отсюда название 'пост-инкремент').

Очень распространенным типом выражений являются выражения сравнения. Они вычисляются в 0 или 1, означающих соответственно FALSE (ложь) или TRUE (истину). PHP поддерживает > (больше), >= (больше либо равно), == (равно), != (не равно), < (меньше) и <= (меньше либо равно). Он также поддерживает операторы строгого равенства: === (равно и одного типа) и !== (не равно или не одного типа). Чаще всего эти выражения используются в условиях выполнения операторов, таких как if.

Последний пример выражений, который мы здесь рассмотрим, это смешанные выражения операции и присвоения. Вы уже знаете, что если вы хотите увеличить $a на 1, вы можете просто написать '$a++' или '++$a'. Но что, если вы хотите прибавить больше, чем единицу, например, 3? Вы могли бы написать '$a++' много раз, однако, очевидно это не очень рациональный или удобный способ. Гораздо более распространенной практикой является запись вида '$a = $a + 3'. '$a + 3' вычисляется в значение $a плюс 3 и снова присваивается $a, увеличивая в результате $a на 3. В PHP, как и в некоторых других языках, таких как C, вы можете записать это более коротким образом, что увеличит очевидность смысла и быстроту понимания кода по прошествии времени. Прибавить 3 к текущему значению $a можно с помощью записи '$a += 3'. Это означает дословно "взять значение $a, прибавить к нему 3 и снова присвоить его переменной $a". Кроме большей понятности и краткости, это быстрее работает. Значением '$a += 3', как и обычного присвоения, является присвоенное значение. Обратите внимание, что это НЕ 3, а суммированное значение $a плюс 3 (то, что было присвоено $a). Таким образом может использоваться любой двухместный оператор, например, '$a -= 5' (вычесть 5 из значения $a), '$b *= 7' (умножить значение $b на 7) и т.д.

Существует еще одно выражение, которое может выглядеть необычным, если вы не встречали его в других языках - тернарный условный оператор:

<?php
$first
? $second : $third
?>

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

Следующий пример должен помочь вам немного улучшить понимание префиксного и постфиксного инкремента и выражений:

<?php
function double($i)
{
    return
$i*2;
}
$b = $a = 5;        /* присвоить значение пять переменным $a и $b */
$c = $a++;          /* постфиксный инкремент, присвоить значение $a
                       (5) переменной $c */
$e = $d = ++$b;     /* префиксный инкремент, присвоить увеличенное
                       значение $b (6) переменным $d и $e */

/* в этой точке и $d, и $e равны 6 */

$f = double($d++);  /* присвоить удвоенное значение $d перед
                       инкрементом (2*6 = 12) переменной $f */
$g = double(++$e);  /* присвоить удвоенное значение $e после
                       инкремента (2*7 = 14) переменной $g */
$h = $g += 10;      /* сначала переменная $g увеличивается на 10,
                       приобретая, в итоге, значение 24. Затем значение
                       присвоения (24) присваивается переменной $h,
                       которая в итоге также становится равной 24. */
?>

Некоторые выражения могут рассматриваться как инструкции. В данном случае инструкция имеет вид 'выражение' ';' - выражение с последующей точкой с запятой. В записи '$b=$a=5;', $a=5 - это верное выражение, но само по себе не инструкция. Тогда как '$b=$a=5;' является верной инструкцией.

Последнее, что стоит упомянуть, это истинность значения выражений. Во многих случаях, как правило, в условных операторах и циклах, вас может интересовать не конкретное значение выражения, а только значат ли они TRUE или FALSE. Константы TRUE и FALSE (регистро-независимые) - это два возможных булевых значения. При необходимости выражение автоматически преобразуется в булев тип. Подробнее о том, как это происходит, смотрите в разделе о приведении типов.

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