Самоучитель по PHP 4
.pdfГлава 7. Переменные, константы, выражения |
131 |
Посмотрим еще раз на этот пример. Помните, я говорил, что практически все, из чего мы составляем программу — это выражения? Так вот, $b=$a —тоже выражение! (Впрочем, это не будет сюрпризом для знатоков Си или Perl). Нетрудно догадаться, какое оно имеет значение: 5 (тут просто не может быть никаких других вариантов, не правда ли?). А это значит, что мы можем написать что-то типа следующих команд:
$a=($b=10); // или просто $a=$b=10
При этом переменным $a и $b присвоится значение 10. А вот еще пример, уже менее тривиальный:
$a=3*sin($b=$c+10)+$d;
Что окажется в переменных после выполнения этих команд? Очевидно, то же, что и в результате работы следующих операторов:
$b=$c+10; $a=3*sin($c+10)+$d;
Мы видим, что в PHP при вычислении сложного выражения можно (если какая-то его часть понадобится нам впоследствии) задавать переменным значения этой части прямо внутри оператора присваивания. Этот прием может действительно сильно упростить жизнь и сократить код программы, "читабельность" которой сохранится на прежнем уровне, так что советую им иногда пользоваться.
Совершенно точно можно сказать, что у любого выражения есть тип его значения. Например:
$a=10*20; $b="".(123*3);
echo "$a:",gettype($a)," $b:",gettype($b); // выведет "200:integer 200:string"
Чтобы преобразовать одно значение в другое (например, нам может не понравиться, что $b — типа string, хотя содержит целое число), используются операторы преобразования типов. Эти операторы доступны как в функциональной, так и в префиксной операторной форме. Например, следующие две инструкции эквивалентны:
$a = intval($b); $a = (int)$b;
Итак, вот эти операторы:
r$b=intval(выражение) или $b=(int)(выражение)
Переводит значение выражения в целое число и присваивает его $b.
r$b=doubleval(выражение) или $b=(double)(выражение)
Переводит значение в действительное число и присваивает его $b.
r$b=strval(выражение) или $b=(string)(выражение)
132 |
Часть III. Основы языка PHP |
Переводит значение выражения в строку.
r$b=(bool)(выражение)
Преобразует значение выражения в логический тип. То есть, после выполнения этого оператора в $b окажется либо true, либо false.
Вообще-то, есть еще два хитроумных оператора (array) и (object), но эти операторы мы рассматривать не будем в силу их крайне слабой распространенности.
Логические выражения
Логические выражения — это выражения, у которых могут быть только два значения: ложь и истина (или, что почти то же самое, 0 и 1). Что, поверили? Напрасно — на самом деле абсолютно любое выражение может рассматриваться как логическое в "логическом" же контексте (например, как условие для конструкции if-else). Ведь, как уже говорилось, в качестве истины может выступать любое ненулевое число, непустая строка и т. д., а под ложью подразумевается все остальное.
Для логических выражений справедливы все те выводы, которые мы сделали насчет логических переменных. Эти выражения чаще всего возникают при применении операторов >, < и == (равно), || (логическое ИЛИ), && (логическое И), ! (логическое НЕ) и других. Например:
$a = 10<5; |
// $a=false |
$a = $b==1; |
// $a=true, åñëè $b=5 |
$a = $b>=1&&$b<=10 |
// $a=true, если $b в пределах от 1 до 10 |
$a = !($b||$c)&&$d; |
// $a=true, если $b и $c ложны, а $d — истинно |
Как осуществляется проверка истинности той или иной логической переменной? Да точно так же, как и любого логического выражения:
$b = $a>=1&&$a<=10; // присваиваем $b значение логического выражения if($b) echo "a в нужном диапазоне значений";
Строковые выражения
Строки в PHP — одни из самых основных объектов. Как мы уже говорили, они могут содержать текст вместе с символами форматирования или даже бинарные данные. Определение строки в кавычках или апострофах может начинаться на одной строке, а завершаться — на другой. Вот пример, который синтаксически совершенно корректен:
$a="Это текст, начинающийся на одной строке и продолжающийся на другой, третьей и т. д.";
Глава 7. Переменные, константы, выражения |
133 |
Я уже много раз использовал в примерах строковые константы, заключенные как в кавычки, так и в апострофы. Настало время поговорить о том, чем эти представления отличаются.
Строка в апострофах
Начнем с самого простого. Если строка заключена в апострофы (например, 'строка'), то она трактуется почти в точности так же, как записана, за исключением двух специальных последовательностей символов:
rпоследовательность \' трактуется PHP как апостроф и предназначена для вставки апострофа в строку, заключенную в апострофы;
rпоследовательность \\ трактуется как один обратный слэш и позволяет вставлять в строку этот символ.
Все остальные символы обозначают сами себя, в частности, символ $ не имеет никакого специального значения (отсюда вытекает, что переменные внутри строки, заключенной в апострофы, не интерполируются, т. е. их значение не подставляется).
Строка в кавычках
По сравнению с апострофами, кавычки более "либеральны". То есть, набор специальных метасимволов, которые, будучи помещены в кавычки, определяют тот или иной специальный символ, гораздо богаче. Вот некоторые из них:
r\n обозначает символ новой строки;
r\r обозначает символ возврата каретки;
r\t обозначает символ табуляции;
r\$ обозначает символ $, чтобы следующий за ним текст случайно не был интерполирован, как переменная;
r\" обозначает кавычку;
r\\ обозначает обратный слэш;
r\xNN обозначает символ с шестнадцатеричным кодом NN.
Переменные в строках интерполируются. Например:
$a="Hello"; echo "$a world!"
Этот фрагмент выведет Hello world!, т. е. $a в строке была заменена на значение переменной $a (этому поспособствовал знак доллара, предваряющий любую переменную).
Давайте рассмотрим еще один пример. $a="Hell"; // слово Hello без буквы "o" echo "$ao world!";
134 |
Часть III. Основы языка PHP |
Мы ожидаем, что выведется опять та же самая строка. Но задумаемся: как PHP узнает, имели ли мы в виду переменную $a или же переменную $ao? Очевидно, никак. Запустив фрагмент, убеждаемся, что он генерирует сообщение о том, что переменная $ao не определена. Как же быть? А вот как:
$a="Hell"; // слово Hello без буквы "o" echo $a."o world!"; // один способ echo "{$a}o world!"; // другой способ echo "${a}o world!"; // третий способ!
Мы видим, что существует целых три способа преодолеть проблему. Каким из них воспользоваться — дело ваше. Мне больше нравится вариант с {$a}, хотя он и введен в PHP лишь недавно.
Последний пример показывает, что в некоторых контекстах и фигурные скобки могут трактоваться как спецсимволы.
Here-документ
В четвертой версии PHP появился и еще один способ записи строковых констант, который исторически называется here-документом (встроенный документ). Фактически он представляет собой альтернативу для записи многострочных констант. Выглядит это примерно так:
$a=<<<MARKER
Далее идет какой-то текст, возможно, с переменными, которые интерполируются:
например, $name будет интерполирована здесь. MARKER;
Строка MARKER может быть любым алфавитно-цифровым идентификатором, не встречающимся в тексте here-документа в виде отдельной строки. Синтаксис накладывает 2 ограничения на here-документы:
rпосле <<<MARKER и до конца строки не должны идти никакие непробельные символы;
rзавершающая строка MARKER; должна оканчиваться точкой с запятой, после которой до конца строки не должно быть никаких инструкций.
Эти ограничения настолько стесняют свободу при использовании here-документов, так что, думаю, вам стоит совсем от них отказаться. Например, следующий код работать не будет, как бы нам этого ни хотелось (функция strip_tags() удаляет тэги из строки):
echo strip_tags(<<<EOD);
Глава 7. Переменные, константы, выражения |
135 |
Какой-то текст с <b>тэгами </b> — этот пример НЕ работает! EOD;
Надеюсь, в будущем разработчики PHP изменят ситуацию к лучшему, но пока они этого не сделали.
Вызов внешней программы
Последняя строковая "константа" — строка в обратных апострофах (например, `команда`), заставляет PHP выполнить команду операционной системы и то, что она вывела, подставить на место строки в обратных апострофах. Вот так, например, мы можем в системе Windows узнать содержимое текущего каталога, которое выдает команда dir:
$st=`dir`;
echo "<pre>$st</pre>";
Впрочем, если в настройках PHP установлен так называемый безопасный режим, который ограничивает возможность запуска внешних программ лишь некоторыми, указанная команда может и не сработать. Мы еще вернемся к запуску программ в следующей части этой книги.
Операции
На самом деле, к этому моменту вы уже знакомы практически со всеми операциями над переменными и выражениями в PHP. И все же я приведу здесь их полный список с краткими комментариями, заменяя выражения-операнды буквами a и b.
В большинстве публикаций, как только разговор заходит о выражениях и опе- рациях, проводят громоздкую и неуклюжую таблицу приоритетов (порядка дей- ствий) и ассоциативности операторов. Пожалуй, я воздержусь от такой практи- ки (ввиду ее крайней ненаглядности) и отошлю интересующихся к официальной документации по PHP. Вместо этого я посоветую вам везде, где возможна хоть малейшая неоднозначность, использовать скобки.
Арифметические операции
ra + b — сложение
ra — b — вычитание
ra * b — умножение
ra / b — деление
ra % b — остаток от деления a на b
136 |
Часть III. Основы языка PHP |
Операция деления / возвращает целое число (то есть, результат деления нацело), если оба выражения a и b — целого типа (или же строки, выглядящие как целые числа), в противном случае результат будет дробным. Операция вычисления остатка от деления % работает только с целыми числами, так что применение ее к дробным может привести к, мягко говоря, нежелательному результату.
Строковые операции
ra.b — слияние строк a и b
ra[n] — символ строки в позиции n
Собственно, других строковых операций и нет — все остальное, что можно сделать со строками в PHP, выполняют стандартные функции.
Операции присваивания
Основным из этой группы операций является оператор присваивания =. Еще раз напомню, что он не обозначает "равенство", а говорит интерпретатору, что значение правого выражения должно быть присвоено переменной слева. Например:
$a = ($b = 4) + 5;
После этого $a равно 9, а $b равно 4.
Обратите внимание на то, что в левой части всех присваивающих операторов должна стоять переменная или ячейка массива.
Помимо этого основного оператора, существует еще множество комбинированных — по одному на каждую арифметическую, строковую и другую операцию. Например:
$a = 10;
$a += 4; // прибавить к $a 4 $s = "Hello";
$s .= " world!"; // теперь в $s "Hello world!"
Думаю, не стоит особо на них задерживаться.
Операции инкремента и декремента
Для операций $a+=1 и $b-=1 в связи с их чрезвычайной распространенностью в PHP ввели, как и в Си, специальные операторы. Итак:
r$a++ — увеличение переменной $a на 1;
r$a-- — уменьшение переменной $a на 1.
Как и в языке Си, эти операторы увеличивают или уменьшают значение переменной, а в выражении возвращают значение переменной $a до изменения. Например:
Глава 7. Переменные, константы, выражения |
137 |
$a=10; $b=$a++;
echo "a=$a, b=$b"; // выведет a=11, b=10
Как видите, сначала переменной $b присвоилось значение переменной $a, а уж затем последняя была инкрементирована. Впрочем, выражение, значение которого присваивается переменной $b, может быть и сложнее — в любом случае, инкремент $a произойдет только после его вычисления.
Существуют также парные рассмотренным операторы, которые указываются до, а не после имени переменной. Соответственно, и возвращают они значение переменной уже после изменения. Вот пример:
$a=10; $b=--$a;
echo "a=$a, b=$b"; // выведет a=9, b=9
Операторы инкремента и декремента на практике применяются очень часто. Например, они встречаются практически в любом цикле for.
Битовые операции
Эти операции предназначены для работы (установки/снятия/проверки) групп битов в целой переменной. Биты целого числа — это не что иное, как отдельные разряды того же самого числа, записанного в двоичной системе счисления. Например, в двоичной системе число 12 будет выглядеть как 1100, а 2 — как 10, так что выражение 12|2 вернет нам число 14 (1110 в двоичной записи). Если переменная не целая, то она вначале округляется, а уж затем к ней применяются перечисленные ниже операторы.
ra & b — результат — число, у которого установлены только те биты, которые установлены и у a, и у b одновременно.
ra | b — результат — число, у которого установлены только те биты, которые установлены либо в a, либо в b (либо одновременно).
r~ a — результат, у которого на месте единиц в a стоят нули, и наоборот.
ra << b — результат — число, полученное поразрядным сдвигом a на b битов влево.
ra >> b — аналогично, только вправо.
Операции сравнения
Это в своем роде уникальные операции, потому что независимо от типов своих аргументов они всегда возвращают одно из двух: false или true. Операции сравнения позволяют сравнивать два значения между собой и, если условие выполнено, возвращают true, а если нет — false.
r a == b — истина, если a равно b.
138 |
Часть III. Основы языка PHP |
ra != b — истина, если a не равно b.
ra < b — истина, если a меньше b.
ra > b — аналогично больше.
ra <= b — истина, если a меньше либо равно b.
ra >= b — аналогично больше либо равно.
Следует отметить, что в PHP сравнивать можно только скалярные (то есть строки и числа) переменные. Для массивов и объектов этого делать нельзя. Их даже нельзя сравнивать на равенство (при помощи оператора ==), но при выполнении такой операции PHP не выдает предупреждения. Так что удивившись как-то раз, почему это два совершенно разных массива при сравнении их с помощью == оказываются вдруг одинаковыми, вспомните, что перед сравнением оба операнда преобразуются в слово array, которое потом и сравнивается.
Операции эквивалентности
В PHP версии 4 появился новый оператор сравнения — тройной знак равенства ===, или оператор проверки на эквивалентность. Как мы уже замечали ранее, PHP довольно терпимо относится к тому, что строки неявно преобразуются в числа, и наоборот. Например, следующий код выведет, что значения переменных равны:
$a=10; $b="10";
if($a==$b) echo "a и b равны";
И это несмотря на то, что переменная $a представляет собой число, а $b — строку. Впрочем, данный пример показывает, каким PHP может быть услужливым, когда нужно. Давайте теперь посмотрим, какой казус может породить эта "услужливость".
$a=0; // ноль
$b=""; // пустая строка if($a==$b) echo "a и b равны";
Хотя $a и $b явно не равны даже в обычном понимании этого слова, программа заявит, что они совпадают. Почему так происходит? Дело в том, что если один из операндов логического оператора может трактоваться как число, то оба операнда трактуются как числа. При этом пустая строка превращается в 0, который затем и сравнивается с нулем. Неудивительно, что оператор echo срабатывает.
Проблему решает оператор эквивалентности === (тройное равенство). Он не только сравнивает два выражения, но также их типы. Перепишем наш пример с использованием этого оператора:
$a=0; // ноль
$b=""; // пустая строка if($a===$b) echo "a и b равны";
Глава 7. Переменные, константы, выражения |
139 |
Вот теперь ничего напечатано не будет. Но возможности оператора эквивалентности идут далеко за пределы сравнения "обычных" переменных. С его помощью можно сравнивать также и массивы, объекты и т. д. Это бывает иногда очень удобно. Вот пример:
$a=array(’a’=>’aaa’); $b=array(’b’=>’bbb’);
if($a==$b) echo "С использованием == a=b<br>"; if($a===$b) echo "С использованием === a=b<br>";
Если запустить представленный код, то выведется первое сообщение, но не второе. Произойдет это по той причине, что, как мы уже говорили, операнды-массивы преобразуются в строки array, которые затем и будут сравниваться. Оператор === лишен этого недостатка, поэтому работает верно.
Разумеется, для оператора === существует и его антипод — оператор !=== (он состоит из целых четырех символов!). Думаю, что не нужно объяснять, как он работает.
Логические операции
Эти операции предназначены исключительно для работы с логическими выражениями и также возвращают false или true.
r! a — истина, если a ложно, и наоборот.
ra && b — истина, если истинны и a, и b.
ra || b — истина, если истинны или a, или b, или они оба.
Следует заметить, что вычисление логических выражений, содержащих такие операции, идет всегда слева направо, при этом, если результат уже очевиден (например, false&&что-то всегда дает false), то вычисления обрываются, даже если в выражении присутствуют вызовы функций. Например, в операторе
$logic = 0&&(time()>100);
стандартная функция time() никогда не будет вызвана.
Будьте осторожны с логическими операциями — не забывайте про удваивание символа. Обратите внимание, что, например, | и || — два совершенно разных оператора, один из которых может потенциально возвращать любое число, а второй — толь-
ко false и true.
Оператор отключения предупреждений
Выдаче ясных и адекватных сообщений о возникших во время выполнения сценария ошибках разработчики PHP заслуженно уделили особое внимание. Наверное, вы уже запускали несколько простых PHP-программ из браузера и имели удовольствие ви-
140 |
Часть III. Основы языка PHP |
деть, что все ошибки выводятся прямо в окно браузера вместе с указанием, на какой строке и в каком файле они обнаружены. Остается только в редакторе найти нужную строку и исправить ошибку. Удобно, не правда ли?
К сожалению, PHP — чуть ли не первый язык, который выводит предупрежде- ния в браузер, а не в файлы журналов. Если вы работали некоторое время с таким языком, как Perl, то, наверное, уже успели устать от бесконечных вере- ниц "500-х ошибок", которые Perl выдает при малейшей оплошности в сцена- рии. Теперь можете вздохнуть с облегчением: PHP никогда не выдаст сообще- ние о 500-й ошибке, что бы ни произошло.
PHP устроен так, что ранжирует ошибки и предупреждения по четырем основным "уровням серьезности". Вы можете настроить его так, чтобы он выдавал только ошибки тех уровней, которые вас интересуют, игнорируя остальные (то есть, не выводя предупреждений о них). Впрочем, я рекомендую всегда включать контроль ошибок по-максимуму, т. к. это может существенно упростить отладку программ. Допустим, мы так и поступили, и теперь PHP "ругается" даже на незначительные ошибки.
Однако не всегда это бывает удобно. Более того, иногда предупреждения со стороны интерпретатора просто недопустимы. Рассмотрим, например, такой сценарий (лис-
тинг 7.4):
Листинг 7.4. Навязчивые предупреждения
<form action=test.php>
<input type=submit name="doGo" value="Click!"> </form>
<?
if($doGo) echo "Вы нажали кнопку!"; ?>
Мы хотели сделать так, чтобы при нажатии на кнопку выдавалось соответствующее сообщение, но вот беда: теперь при первом запуске сценария PHP выдаст предупреждение о том, что "переменная $doCliсk не инициализирована". Ну не отключать же из-за такой мелочи контроль ошибок во всем сценарии, не правда ли? Как бы нам временно блокировать проверку ошибок, чтобы она не действовала только в одном месте, не влияя на остальной код?
Вот для этого и существует оператор @ (отключение ошибок). Если разместить данный оператор перед любым выражением (возможно, включающим вызовы функций, генерирующих предупреждения), то сообщения об ошибках в этом выражении будут подавлены и в окне браузера не отображены.