Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Самоучитель по PHP 4

.pdf
Скачиваний:
61
Добавлен:
02.05.2014
Размер:
4.36 Mб
Скачать

Глава 7. Переменные, константы, выражения

121

Эта программа выводит оба раза значение 1, во всяком случае, в моей версии

PHP 4.03.

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

Действия с переменными

Вне зависимости от типа переменной, с ней можно делать три основных действия.

Присвоение значения

Мы можем присвоить переменной значение другой переменной (или значение, возвращенное функцией), ссылку на другую переменную, либо же константное выражение (за исключением объектов, для которых вместо этого используется оператор new). Как уже говорилось, за преобразование типов отвечает сам интерпретатор. Кроме того, при присваивании старое содержимое и, что самое важное, тип переменной теряются, и она становится абсолютно точной копией своего "родителя". То есть, если мы массиву присвоим число, это сработает, однако весь массив при этом будет утерян.

Проверка существования

Можно проверить, существует ли (то есть, инициализирована ли) указанная переменная. Осуществляется это при помощи оператора IsSet(). Например:

if(IsSet($MyVar))

echo "Такая переменная есть. Ее значение $MyVar";

Если переменной в данный момент не существует (то есть нигде ранее ей не присваивалось значение, либо же она была вручную удалена при помощи Unset()), то IsSet() возвращает ложь, в противном случае — истину.

Важно помнить, что мы не можем использовать неинициализированную переменную в программе — иначе это породит предупреждение со стороны интерпретатора (что, скорее всего, свидетельствует о наличии логической ошибки в сценарии). Конечно, предупреждения можно выключить, тогда все неинициализированные переменные будут полагаться равными пустой строке. Однако я категорически не советую вам этого делать — уж лучше лишняя проверка присутствия в коде, чем дополнительная возня с "отлавливанием" возможной ошибки в будущем. Если вы все же захотите отключить это злополучное предупреждение (а заодно и все остальные), лучше ис-

122

Часть III. Основы языка PHP

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

Уничтожение

Уничтожение переменной реализуется оператором Unset(). После этого действия переменная удаляется из внутренних таблиц интерпретатора, т. е. программа начинает выполняться так, как будто переменная еще не была инициализирована. Например:

//Переменной $a еще не существует $a="Hello there!";

//Теперь $a инициализирована

//... какие-то команды, использующие $a echo $a;

//А теперь удалим переменную $a

Unset($a);

// Теперь переменной $a опять не существует echo $a; // Ошибка: нет такой переменной $a

Впрочем, применение Unset() для работы с обычными переменными редко бывает целесообразно. Куда как полезнее использовать его для удаления элемента в ассоциативном массиве. Например, если в массиве $A нужно удалить элемент с ключом for_del, это можно сделать так:

Unset($A["for_del"]);

Теперь элемент for_del не просто стал пустым, а именно удалился, и последующий перебор элементов массива его не обнаружит.

Определение типа переменной

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

ris_integer($a)

Возвращает true, если $a — целое число.

ris_double($a)

Возвращает true, если $a — действительное число.

ris_string($a)

Возвращает true, если $a является строкой.

ris_array($a)

Возвращает true, если $a является массивом.

Глава 7. Переменные, константы, выражения

123

ris_object($a)

Возвращает true, если $a объявлена как объект.

ris_boolean($a)

Возвращает true, если $a определена как логическая переменная.

rgettype($a)

Возвращает строки, соответственно, со значениями: array, object, integer, double, string, boolean или unknown type в зависимости от типа перемен-

ной.

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

Установка типа переменной

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

settype($a,$type)

Функция пытается привести тип переменной $a строк, возвращаемых gettype(), кроме boolean пример, в $a "нечисловая" строка,

($a,"integer")), возвращает false.

к типу $type ($type — одна из ). Если это сделать не удалось (на- а мы вызываем settype

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

Сильно не ошибусь, если скажу, что нет на свете такой программы, в которой не было бы ни одного оператора присваивания. И в PHP-программе этот оператор, конечно же, тоже есть. Мы уже с ним встречались — это —знак равенства =:

$имя_переменной=значение;

Как видите, разработчики PHP пошли по линии Си в вопросе операторов присваивания (и проверки равенства, которая обозначается ==), чем, я уверен, привнесли свой вклад в размножение многочисленных ошибок. Например, если в Си мы пишем

if(a=b) { ... }

вместо

if(a==b) { ... }

124

Часть III. Основы языка PHP

(пропуская ненароком один символ равенства), то компилятор выдаст нам по крайней мере предупреждение. Иначе обстоит дело в PHP: попробуйте как-нибудь на досуге написать:

$a=0; $b=1;

if($a=$b) echo "a и b одинаковы"; else echo "a и b различны";

Интерпретатор даже не "пикнет", а программа восторженно заявит, что "a и b одинаковы", хотя это, очевидно, совсем не так (дело в том, что $a=$b так же, как и $a+$b, является выражением, значение которого есть правая часть оператора присваивания, равная в нашем примере 1).

Почему разработчики PHP пошли таким путем, хотя, я уверен, отлично пони- мали его недостатки (двух мнений тут быть просто не может)? Что бы им стои- ло вместо = использовать (например, как в Паскале) :=, а вместо == =? Я не знаю. Зато знаю, что в PHP есть еще несколько "ляпов" (только давайте не будем разжигать религиозных войн по поводу оператора == каждый про- граммист волен иметь свое мнение), перенятых из Си. Так что призываю вас быть предельно внимательными тут могут поджидать очень даже неприят- ные сюрпризы.

Ссылочные переменные

Хотя в PHP нет такого понятия, как указатель (что, возможно, к лучшему, а скорее всего — нет), все же можно создавать ссылки на другие переменные. Существует две разновидности ссылок: жесткие и символические (первые часто называют просто ссылками). Жесткие ссылки появились лишь в PHP версии 4 (в третьей версии существовали лишь символические ссылки).

Жесткие ссылки

Жесткая ссылка представляет собой просто переменную, которая является синонимом другой переменной. Многоуровневые ссылки (то есть, ссылка на ссылку на переменную, как это можно делать, например, в Perl) не поддерживаются. Так что, думаю, не стоит воспринимать жесткие ссылки серьезнее, чем синонимы.

Чтобы создать жесткую ссылку, нужно использовать оператор & (амперсанд). Например:

$a=10;

$b = &$a; // теперь $b — то же самое, что и $a $b=0; // на самом деле $a=0

echo "b=$b, a=$a"; // выводит "b=0, a=0"

Глава 7. Переменные, константы, выражения

125

Ссылаться можно не только на переменные, но и на элементы массива (этим жесткие ссылки выгодно отличаются от символических). Например:

$A=array('a' => 'aaa', 'b' => 'bbb');

$b=&$A['b']; // теперь $b — то же, что и элемент с индексом 'b' массива $b=0; // на самом деле $A['b']=0;

echo $A['b']; // выводит 0

Впрочем, элемент массива, для которого планируется создать символическую ссылку, может и не существовать. Как в следующем случае:

$A=array('a' => 'aaa', 'b' => 'bbb');

$b=&$A['c']; // теперь $b — то же, что и элемент с индексом 'c' массива echo "Элемент с индексом 'c': (".$A['c'].")";

В результате выполнения этой программы, хотя ссылке $b и не было ничего присвоено, в массиве $A создастся новый элемент с ключом c и значением — пустой строкой (мы можем это определить по результату работы echo). То есть, жесткая ссылка на самом деле не может ссылаться на несуществующий объект, а если делается такая попытка, то объект создается.

Попробуйте убрать строку, в которой создается жесткая ссылка, и вы тут же получите сообщение о том, что элемент с ключом c не определен в массиве $A.

И все же, жесткая ссылка — не абсолютно точный синоним объекта, на который она ссылается. Дело в том, что оператор Unset(), выполненный для жесткой ссылки, не удаляет объект, на который она ссылается, а всего лишь разрывает связь между ссылкой и объектом.

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

Итак, жесткая ссылка и переменная (объект), на которую она ссылается, совершенно равноправны, но изменение одной влечет изменение другой. Оператор Unset() разрывает связь между объектом и ссылкой, но объект удаляется только тогда, когда на него никто уже не ссылается.

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

126

Часть III. Основы языка PHP

Символические ссылки

Символическая ссылка — это всего лишь строковая переменная, хранящая имя другой переменной. Чтобы добраться до значения переменной, на которую ссылается символическая ссылка, необходимо применить оператор разыменования — дополнительный знак $ перед именем ссылки. Давайте разберем пример:

$a=10; $b=20; $c=30;

$p="a"; // или $p="b" или $p="c" (присваиваем $p имя другой переменной) echo $$p; // выводит переменную, на которую ссылается $p, т. е. $a $$p=100; // присваивает $a значение 100

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

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

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

Некоторые условные обозначения

Как мы уже знаем, в PHP нет необходимости указывать тип какой-либо переменной или выражения явно. Однако, как мы видели, с каждой величиной в программе все же ассоциирован конкретный тип, который, впрочем, можно поменять в процессе выполнения программы. Такие "подмены" будут вполне осмысленными, если, например, мы к строке "20" прибавим число 10 и получим результат 30 (а не "2010") — это хороший пример того, как PHP выполняет преобразования из числа в строку и наоборот.

Но представьте себе, что мы хотим привести тип переменной $a к числу, а она на самом деле — массив. Ясно, что такое преобразование лишено всякого смысла — о чем вам и сообщит (в лучшем случае) PHP, если вы попытаетесь, например, прибавить $a к 10. А может и не сообщить (скажем, если перевести массив в строку, то всегда получится строка "Array"). В то же время, дальше, когда мы будем рассмат-

Глава 7. Переменные, константы, выражения

127

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

<return_type> FuncName(<type1> $param1 [,<type1> $param2])

Функция делает то-то и то-то. Возвращает то-то.

Здесь должно быть приведено описание функции, возвращающей значение типа <return_type>, и принимающей один или два аргумента (второй аргумент необязательный, на что указывают квадратные скобки). Тип первого параметра <type1>, а второго — <type2>. Описание возможных типов, которые я здесь выделил угловыми скобками, приводится в следующих подразделах.

string

Обычная строка, или тип, который можно перевести в строку.

int, long

Целое число, либо вещественное число (в последнем случае дробная часть отсекается), либо строка, содержащая число в одном из перечисленных форматов. Если строку не удается перевести в int, то вместо нее подставляется 0, и никаких предупреждений не генерируется!

double, float

Вещественное число, или целое число, или строка, содержащая одно из таких чисел.

bool

Логический тип, который будет восприниматься либо как ложь (нулевое число, пустая строка или константа false), либо как истина (все остальное). Обычно редко указывается этот тип (вместо него пишут int, хотя это и неверно), но я все же постараюсь применять его там, где это возможно.

array

Массив, в общем случае ассоциативный (см. ниже). То есть набор пар ключ=>значение. Впрочем, здесь может быть передан и список list.

128

Часть III. Основы языка PHP

list

Обычно это массив с целыми ключами, пронумерованными от 0 и следующими подряд. Так как список является разновидностью ассоциативного массива, то обычно вместо параметров функций типа list можно подставлять и параметры типа array. При этом, скорее всего, функция "ничего не заметит" и будет работать с этим массивом как со списком, "мысленно" пронумеровав его элементы. Можно также сказать, что список представляет собой упорядоченный набор значений (который можно, например, отсортировать в порядке возрастания), тогда как ассоциативный массив — упорядоченный набор пар значений, каждую из которых логически бессмысленно разъединять.

object

Объект какой-то структуры. Обычно эта структура будет уточняться.

void

Пожалуй, самый простой тип, который применяется только для определения возвращаемого функцией значения, я бы его охарактеризовал так: "Не возвращает ничего ценного". В PHP функция не может ничего не возвращать (так уж он устроен), поэтому практически все void-функции возвращают false (то есть пустую строку).

mixed

Все, что угодно. Это может быть целое или дробное число, строка, массив или объект... Например, параметр типа mixed имеет стандартная функция gettype() или функция settype(). Если написано, что функция возвращает mixed, это значит, что тип результата зависит от операндов и уточняется при описании функции.

При написании функций ни в коем случае не набирайте эти имена типов! Они нуж- ны только для того, чтобы уточнить синтаксис какой-то функции. Хотя, возможно, в будущих версиях эти типы все же можно будет указывать явно. Что ж, посмотрим...

Константы

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

Глава 7. Переменные, константы, выражения

129

Константа отличается от переменной тем, что, во-первых, ей нигде в программе нельзя присвоить значение больше одного раза, а во-вторых, ее имя не предваряется знаком $, как это делается для переменных. Например:

// Предположим, определена константа PI, равная 3.146

$a=2.34*sin(3*PI/8)+5;

// использование константы

echo "Это число PI";

// выведет "Это число PI"

echo "Это число ".PI;

// выведет "Это число 3.14"

То, что не надо писать "доллар" перед именем константы — это, конечно хорошо. Однако, как мы можем видеть из примера, есть и минусы: мы уже не можем использовать имя константы непосредственно в текстовой строке.

Предопределенные константы

Константы бывают двух типов: одни — предопределенные (то есть устанавливаемые самим интерпретатором), а другие определяются программистом. Существуют несколько предопределенных констант.

r__FILE__

Хранит имя файла программы, которая выполняется в данный момент.

r__LINE__

Содержит текущий номер строки, которую обрабатывает в текущий момент интерпретатор. Эта своеобразная "константа" каждый раз меняется по ходу исполнения программы.

rPHP_VERSION

Версия интерпретатора PHP.

rPHP_OS

Имя операционной системы, под которой работает PHP.

rTRUE или true

Эта константа нам уже знакома и содержит значение "истина".

rFALSE или false

Содержит значение "ложь".

Определение констант

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

130

Часть III. Основы языка PHP

void define(string $name, string $value, bool $case_sen=true);

Определяет новую константу с именем, переданным в $name, и значением $value. Если необязательный параметр $case_sen равен true, то в дальнейшем в программе регистр букв константы учитывается, в противном случае — не учитывается (по умолчанию, как мы видим, регистр учитывается). Созданная константа не может быть уничтожена или переопределена.

Например:

define("pi",3.14); define("str","Test string"); echo sin(pi/4);

echo str;

Прошу обратить внимание на кавычки, которыми должно быть обрамлено имя константы при ее определении. А также на то, что нельзя дважды определять константу с одним и тем же именем — это породит ошибку во время выполнения программы.

Проверка существования константы

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

bool defined(string $name)

Возвращает true, если константа с именем $name была ранее определена.

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

Выражения

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

Самый простой пример выражения — переменная или константа, стоящая, скажем, в правой части оператора присваивания. Например, цифра 5 в операторе

$a=5;

есть выражение, т. к. оно имеет значение 5. После такого присваивания мы вправе ожидать, что в $a окажется 5. Теперь, если мы напишем

$b=$a;

то, очевидно, в $b окажется также 5, ведь выражение $a в правой части оператора имеет значение 5.