Оглавление
Разделение логики и содержимого
Введение в регулярные выражения
РНР — это серверный язык создания сценариев. В HTML-страницу можно внедрить код РНР, который будет выполняться при каждом ее посещении. Код РНР интерпретируется Web-сервером и генерирует HTML или иной вывод, наблюдаемый посетителем страницы.
Разработка РНР была начата в 1994 г. и вначале выполнялась одним человеком, Расмусом Лердорфом (Rasmus Lerdorf). Этот язык был принят рядом талантливых людей и претерпел три основных редакции, пока не стал широко используемым и зрелым продуктом, с которым мы имеем дело сегодня. Количество доменов, в которых в настоящее время используется РНР, можно выяснить на странице http://www.php.net/usage.php.
РНР — это продукт с открытым исходным кодом (Open Source). У пользователя имеется доступ к исходному коду. Его можно использовать, изменять и свободно распространять другим пользователям или организациям.
Первоначально РНР являлось сокращением от Personal Home Page (Персональная начальная страница), но затем это название было изменено в соответствии с рекурсивным соглашением по наименованию GNU (GNU = Gnu's Not Unix) и теперь означает РНР Hypertext Preprocessor (Препроцессор гипертекста РНР).
Некоторые преимущества РНР
РНР исключительно эффективен. Используя единственный недорогой сервер, можно обслуживать миллионы обращений в день. Результаты тестирования, опубликованные компанией Zend Technologies (http://www.zend.com), подтверждают более высокую производительность РНР по сравнению с конкурирующими продуктами.
РНР обладает встроенной связностью со многими системами баз данных. В дополнение к MySQL, в числе прочих можно непосредственно подключаться к базам данных PostgreSQL, mSQL, Oracle, dbm, Hyperware, Informix, InterBase и Sybase. Используя Open Database Connectivity Standard (Стандарт открытого интерфейса связи с базами данных, ODBC), можно подключаться к любой базе данных, для которых существует ODBC-драйвер. Это распространяется на продукты Microsoft и многих других компаний.
Поскольку РНР был разработан для использования в Web, он имеет множество встроенных функций для выполнения широкого разнообразия полезных, связанных с Web, задач. С его помощью можно "на лету" генерировать GIF-изображения, подключаться к другим сетевым службам, отправлять сообщения электронной почты, работать с cookie-наборами и генерировать PDF-документы — и все это посредством всего нескольких строк кода.
Пакет РНР является бесплатным. Наиболее новую версию можно в любой момент совершенно бесплатно выгрузить из http://www.php.net.
Синтаксис РНР основывается на других языках программирования, в первую очередь на С и Perl. Если вы уже знакомы с С, Perl или С-подобным языком, таким как C++ или Java, то почти сразу сможете эффективно использовать РНР.
Пакет РНР можно использовать под управлением многих различных операционных систем. Код РНР можно создавать в среде таких бесплатных Unix-подобных операционных систем, как Linux и FreeBSD, коммерческих версий Unix типа Solaris и IRIX или различных версий Microsoft Windows. Как правило, программы будут работать без каких-либо изменений в различных средах с установленным РНР.
Пользователь имеет доступ к исходному коду РНР. В отличие от коммерческих закрытых программных продуктов, если нужно что-либо изменить или добавить в этом языке, то это всегда можно сделать. Не следует дожидаться, пока фирма-изготовитель выпустит правки (патчи). Нет необходимости беспокоиться о том, что изготовитель собирается покинуть рынок или перестанет поддерживать продукт.
Листинг 1.1 orderform.html — HTML-код для базовой формы заказа.
<form action="processorder .php" method=post>
<table border=0><tr bgcolor=#cccccc>
<td width=150>Наименование</td>
<td width=15>Количество</td>
</tr><tr>
<td>Тетрадь</td>
<td align=center><input type="text" name="copybook" size=3 maxlength=3></td>
</tr><tr>
<td>Карандаш</td>
<td align=center><input type="text" name="pencil" size=3 maxlength=3></td>
</tr><tr>
<td>Ручка синяя</td>
<td align=center><input type="text" name="pen" size=3 maxlength=3></td>
</tr><tr>
<td colspan=2 align=center><input type=submit value="Заказать"</td>
</tr>
</table>
</form>
В общем случае значением атрибута ACTION является URL-адрес, который будет загружаться при нажатии пользователем кнопки отправки (submit). Данные, введенные пользователем в форму, будут отправляться по этому URL-адресу с использованием метода, указанного в атрибуте METHOD: либо GET (данные присоединяются в конец URL-адреса), либо POST (данные отправляются в виде отдельного пакета).
Следует обратить внимание на имена полей формы — pen, pencil,copybook. Эти имена будут снова использоваться в PHP-сценарии. Поэтому полям формы важно присваивать осмысленные имена, которые легко запомнить при написании РНР-сценария. Некоторые HTML-редакторы по умолчанию будут генерировать имена полей типа field23. Подобные имена трудно запомнить. Ваша задача как программиста на РНР существенно упростится, если эти имена будут отражать вводимые в поле данные.
Обработка формы
Для обработки формы потребуется создать сценарий, упомянутый в атрибуте ACTION дескриптора FORM и названный processorder.php. Необходимо создать этот файл. Для этого введите следующий код:
<html><head>
<title>Школьник – результат заказа</title>
</head><body>
<hl>ОАО «Школьник»</hl>
<h2>Результат заказа</h2>
<? echo "<p>Заказ обработан...";
echo date("H:i, j, S F") ; ?>
</body></html>
PHP-код интерпретируется и выполняется на Web-сервере, в отличие от JavaScript и других технологий клиентской стороны, которые интерпретируются и выполняются в среде Web-браузера на компьютере пользователя.
Теперь код в рассматриваемом файле состоит из четырех частей:
• HTML
• Дескрипторы РНР
• Операторы РНР
• Пробелы
В него можно добавить также еще одну часть
• Комментарии
Большинство строк в приведенном примере — всего лишь простой HTML-код.
Использование РНР-дескрипторов
PHP-код из предыдущего примера начинается с последовательности <? и завершается последовательностью ?>. Это аналогично всем HTML-дескрипторам, поскольку все они начинаются с символа "меньше" (<) и завершаются символом "больше" (>). Эти символы называются PHP-дескрипторами, поскольку они указывают Web-серверу, где начинается, а где завершается PHP-код. Любой текст, расположенный между дескрипторами, будет интерпретироваться как PHP-код. Любой текст вне этих дескрипторов будет обрабатываться как обычный HTML-код. РНР-декрипторы позволяют выполнить выход из HTML.
Существуют различные стили дескрипторов. В приведенном примере используется сокращенный стиль. Возникновение каких-либо проблем при выполнении приведенного сценария может быть связано с тем, что сокращенные дескрипторы не активизированы в установках РНР. Давайте подробнее рассмотрим стили дескрипторов.
Стили РНР-дескрипторов
Фактически существует четыре различных стиля РНР-дескрипторов. Все приведенные ниже фрагменты кода эквивалентны.
• Сокращенный стиль
<? echo "<p>Заказ обработан."; ?>
Данный стиль дескрипторов является самым простым и соответствует стилю инструкций обработки SGML (Standard Generalized Markup Language — стандартный обобщенный язык разметки).
• XML-стиль
<?php echo "<p>Заказ обработан.";?>
Этот стиль дескрипторов может использоваться в документах XML (Extensible Markup Language — расширяемый язык разметки). Если планируется обслуживание на сайте XML-документов, следует применять именно этот стиль дескрипторов.
• SCRIPT-стиль
<SCRIPT LANGUAGE='php'> echo "<p>Заказ обработан."; </SCRIPT>
Этот стиль дескрипторов является самым длинным и будет знакомым тем, кому приходилось работать с JavaScript или VBScript. Он может использоваться в случае применения HTML-редактора, у которого возникают проблемы с другими стилями дескрипторов.
• ASP-стиль
<% echo "<p>Заказ обработан."; %>
Этот стиль дескриптора совпадает с используемым в Active Server Pages (ASP). Он может применяться, если включен параметр настройки конфигурации asp_tags. Использование этого стиля дескрипторов может потребоваться в случае работы с редактором, ориентированным на ASP, либо если основное кодирование выполняется в ASP.
PHP-операторы
Действия, которые должен выполнить PHP-интерпретатор, указываются РНР-операторами, помещаемыми между открывающим и закрывающим дескрипторами. В следующем примере используется только один тип оператора:
echo "<p>Заказ обработан.";
конструкция echo приводит к очень простому результату; она выводит (или повторяет) в окне браузера переданную ей строку. В конце оператора echo присутствует точка с запятой. Этот символ используется для разделения PHP-операторов.
Пробелы
Символы пропусков, такие как пустые строки (возвраты каретки), пробелы между словами и символы табуляции обобщенно называют пробелами. Пробелы между PHP-операторами не требуются, однако размещение каждого оператора в отдельной строке облегчает чтение кода. Например, фрагменты
Комментарии
Комментарии — это именно то, что следует из их названия: комментарии в коде служат примечаниями для людей, читающих текст кода. Комментарии могут использоваться для пояснения назначения сценария, сообщения информации о его создателе, пояснения, почему он написан именно таким образом, сообщения о времени его последнего изменения и т.п. Как правило, комментарии присутствуют во всех РНР-сценариях, за исключением простейших.
PHP-интерпретатор будет игнорировать любой текст, находящийся в комментарии. По существу, программа синтаксического анализа РНР попросту пропускает комментарии, которые для нее равнозначны пробелам.
РНР поддерживает комментарии в стилях С, C++ и сценариев оболочки Вот как выглядит многострочный комментарий в стиле С, который может появляться в начале РНР-сценария: Многострочные комментарии должны начинаться с символов /* и завершаться символами */. Как и в С, многострочные комментарии не могут быть вложенными.
Можно также использовать однострочные комментарии в стиле C++: все, следующее за символом комментария (#
или //) вплоть до конца строки или до завершающего дескриптора РНР. в зависимости от того, что встретится раньше, рассматривается как комментарий.
Функция date()
Аргумент, передаваемый в функцию date(), должен быть строкой формата, задающей требуемый стиль вывода. Каждая буква в строке представляет часть строки даты и времени. Н представляет часы в 12-часовом формате, i — минуты с ведущим нулем, когда это требуется, j — день месяца без ведущего нуля, S представляет обычный суффикс (в данном случае "th"), a F - - год, представленный четырьмя цифрами.
Доступ к переменным формы
Внутри PHP-сценария к каждому из полей формы можно получить доступ как к переменной, имеющей то же имя, что и у поля формы. Давайте рассмотрим пример.
Добавьте следующие строки в нижнюю часть РНР-сценария:
echo "<p>Ваш заказ:";
echo "<br>";
echo $copybook." тетрадей<br>";
echo $pencil." карандашей<br>";
echo $pen." ручек синих<br>";
Переменные формы
В конечном счете данные из сценария попадают в PHP-переменные. Имена переменных в РНР легко узнать, поскольку все они начинаются с символа доллара ($). Существуют два способа доступа к данным формы через переменные. В этом примере для ссылки на переменные формы используется сокращенный стиль. В данном случае имена переменных в сценарии совпадают с именами в HTML-форме. Так всегда происходит при сокращенном стиле. Переменные не обязательно объявлять в сценарии, поскольку они передаются в сценарий по существу так же, как аргументы передаются в функцию. При использовании этого стиля можно, например, просто начать работать с переменной, скажем, $pen, как и было сделано перед этим.
Второй стиль заключается в получении переменных формы через один из двух массивов, хранящихся в переменных $HTTP_POST_VARS и $HTTP_GET_VARS. Один из этих массивов будет содержать подробную информацию о всех переменных формы. Выбор используемого массива зависит от метода отправки формы: POST или GET. В рамках этого стиля для доступа к данным, введенным в поле формы pen в предыдущем примере, следовало бы использовать $HTTP_POST_VARS ["pen"]
Сокращенный стиль можно применять только при установке в значение "On" директивы register_globals в файле php.ini. Это — настройка по умолчанию в стандартном файле php.ini.
Если же необходимо, чтобы директива register_globals была установлена в значение «Off», придется воспользоваться вторым стилем. При этом придется также установить в значение "On" директиву track_vars.
Более длинный стиль обеспечит более быстрое выполнение и предотвратит создание переменных, которые могут оказаться лишними. С другой стороны, сокращенный стиль проще читать и применять; к тому же он совпадает со стилем, используемым в предыдущих версиях РНР. Оба эти метода аналогичны методам, используемым в других языках создания сценариев, например, Perl, и могут выглядеть знакомо.
Конкатенация строк
В сценарии оператор echo применялся для вывода значений, введенных пользователем в каждом из полей формы, за которыми следовал некоторый пояснительный текст. Если внимательно присмотреться к операторам echo, можно заметить, что между именем переменной и следующим за ним текстом содержится точка (.), например:
echo $pen. " ручек синих<br>";
Это операция конкатенации строк, которая используется для объединения строк (фрагментов текста).
Также возможно: echo" $pen ручек синих<br>";
Переменные и литералы
Переменные и строки, объединяемые в каждом из операторов echo, — суть различные понятия. Переменные — это символы (обозначения) для данных. Строки же — это собственно данные. Фрагмент неструктурированных данных в программе наподобие рассматриваемой называется литералом, в отличие от переменной. $pen — это переменная, т.е. символ, который представляет введенные клиентом данные. С другой стороны, "ручек синих" — это литерал. Он принимается так, как выглядит.
Фактически, в РНР существует два вида строк — с двойными кавычками и одинарными кавычками. РНР будет пытаться оценить строки, заключенные в двойные кавычки, что приводит к поведению, которое наблюдалось ранее. Строки, заключенные в одинарные кавычки, будут обрабатываться как истинные литералы.
Идентификаторы
Идентификаторы — это имена переменных. Идентификаторы подчиняются некоторым простым правилам:
• Идентификаторы могут иметь любую длину и состоять из букв, цифр, символов подчеркивания и знаков доллара. Однако при использовании в идентификаторах знаков доллара следует проявлять внимательность.
• Идентификаторы не могут начинаться с цифры.
• В РНР идентификаторы чувствительны к регистру. Исключение из этого правила составляют встроенные PHP-функции — их имена могут вводиться в любом регистре.
• Идентификаторы переменных могут совпадать с именами встроенных функций.
Однако это обычно вызывает путаницу, потому подобных ситуаций следует избегать. Нельзя также создавать функции, идентификаторы которых совпадают с идентификаторами встроенных функций.
Переменные, объявляемые пользователем
В дополнение к переменным, передаваемым из HTML-формы, можно объявлять и использовать свои собственные переменные. Одна из особенностей РНР заключается в том, что переменные не обязательно объявлять прежде, чем их можно будет использовать. Переменная будет создаваться при первом присвоении ей значения.
Значения переменным присваиваются при помощи операции присваивания =. На сайте компании «Школьник» требуется подсчитать общее количество деталей и общую сумму оплаты. Для хранения этих чисел можно создать две переменные. Для начала они инициализируются нулевыми значениями.
Добавьте следующие строки в нижнюю часть РНР-сценария:
$totalqty = 0 ;
$totalamount = 0.00;
Каждая из двух приведенных строк создает переменную и присваивает ей литеральное значение. Переменным можно присваивать также значения других переменных, например:
$totalqty = 0;
$totalamount = $totalqty;
Типы данных РНР
РНР поддерживает следующие типы данных:
• Integer (целый) — Используется для целых чисел
• Double (двойной точности) — Используется для действительных чисел
• String (строковый) — Используется для строк символов
• Array (массив) — Используется для хранения нескольких элементов данных одного типа
• Object (объект) — Используется для хранения экземпляров классов
РНР поддерживает также типы pdfdoc и pdfinfo, если он был установлен с поддержкой PDF (Portable Document Format — формат переносимых документов).
Преимущества типов
Язык РНР весьма либерален по отношению к типам. В большинстве языков программирования переменные могут содержать только один тип данных, и этот тип должен быть объявлен прежде, чем переменную можно будет использовать, как это имеет место в С. В РНР тип переменной определяется присвоенным ей значением.
Например, при создании переменных Stotalqty и Stotalamount их начальные типы были определены следующим образом:
$totalqty = 0;
$totalamount = 0.00;
Поскольку переменной Stotalqty было присвоено целочисленное значение 0, эта переменная имеет тип integer. Аналогично, переменная Stotalamount имеет тип double. Как ни странно, в сценарий вполне можно было бы добавить следующую строку: $totalamount = "Hello"; В этом случае переменная Stotalamount получила бы тип string. PHP в любой момент времени изменяет тип переменной в соответствиис данными, хранящимися в ней.
Подобная возможность изменения типов "на лету" может оказаться исключительно полезной. Помните, что РНР "автоматически" распознает тип данных, помещаемых в переменные. При чтении данных из переменной возвращаются данные в точности хранимого типа.
Приведение типов
Используя приведение типов, можно имитировать, будто переменная или значение имеет другой тип. Приведение выполняется так же, как и в С. Для этого достаточно перед переменной, тип которой требуется преобразовать, поместить в круглых скобках временный тип.
Например, две созданные выше переменные можно было бы объявить с использованием приведения типов.
$totalqty = 0;
$totalamount = (double)$totalqty;
Вторая строка означает "Взять значение, хранящееся в переменой Stotalqty, интерпретировать как значение типа double и сохранить в переменной Stotalamount". Переменная Stotalamount будет иметь тип double. Приведение типов не изменяет типы, поэтому типом переменной Stotalqty остается integer.
Переменные переменных
РНР предоставляет еще один тип переменных — т.н. переменные переменных. Переменные переменных позволяют динамически изменять имена переменных. (Как видите, РНР допускает очень большую свободу в этом вопросе — все языки разрешают изменять значение переменной, но лишь немногие позволяют изменять тип переменной, а уж совсем немногие — имя переменной.)
Способ достижения этого заключается в использовании значения одной переменной в качестве имени другой. Например, можно было бы определить $varname = "pen";
Затем вместо $tireqty можно использовать $$varname, например, так: $$varname = 5;
Вместо того чтобы перечислять и использовать каждую переменную формы отдельно, можно организовать цикл и переменную для автоматической обработки всех из них. Пример, иллюстрирующий такой метод, приводится в разделе, посвященном циклам for.
Константы
Как было показано ранее, значение, хранящееся в переменной, можно изменять. Кроме того, допускается также объявление констант. Как и переменная, константа хранит значение, но ее значение устанавливается однажды и впоследствии в сценарии изменяться не может.
В нашем примере приложения цены всех продаваемых товаров можно было бы хранить в виде констант. Такие константы определяются с использованием функции define:
define("copybookPRICE", 100);
define("pencilPRICE", 10) ;
define("penPRICE", 4) ;
Вы должны были заметить, что все имена констант записываются прописными. Это соглашение заимствовано из языка С и оно упрощает зрительное различение переменных и констант. Соблюдать соглашение вовсе не обязательно, тем не менее, следует помнить, что оно облегчает чтение и работу с кодом.
Теперь у нас имеются три константы, которые можно использовать для вычисления общей суммы заказа клиента.
Важное различие между константами и переменными заключается в том, что обращение к константе не требует присутствия перед ней знака доллара. Если требуется использовать значение константы, указывайте только ее имя. Например, для вывода одной из только что созданных констант применяется код:
echo penPRICE;
Наряду с константами, определяемыми пользователем, РНР определяет большое количество собственных констант. Эти константы можно легко просмотреть, выполнив команду phpinfo();
В результате выводится список предопределенных переменных и констант PHP, a также другая полезная информация.
Область действия переменных
Термин область действия (scope) относится к разделам сценария, внутри которых видна (доступна) конкретная переменная. В РНР используются следующие три основных типа областей действия:
• Глобальные переменные, объявленные в сценарии, видны во всем сценарии, но не внутри функций.
• Переменные, использованные внутри функции, являются локальными для данной функции.
• Переменные, использованные внутри функции, которая объявлена как глобальная, относятся к глобальным переменным с такими же именами.
Пока достаточно заявить, что все используемые переменные по умолчанию будут глобальными.
Знаки операций
Знаки операций — это символы, которые можно использовать для манипуляции значениями и переменными путем выполнения над ними операций. Некоторые из этих операций потребуются для вычисления общей суммы и налога для заказа клиента. Мы уже упоминали две операции: операцию присваивания (=) и операцию конкатенации строк (.) Теперь давайте ознакомимся с полным списком операций. В общем случае операции могут выполняться над одним, двумя и тремя аргументами, причем большинство из них выполняется над двумя аргументами. Например, операция присваивания принимает два аргумента — адрес, указываемый слева от символа =, и выражение, указываемое справа. Эти аргументы называются операндами, т.е. элементами, с которыми должна выполняться операция.
Арифметические операции
Знак операции Название Пример
+ Сложение $а + $b
- Вычитание $а - $b
* Умножение $а * $b
/ Деление $а / $b
% Взятие модуля $а % $b
Символ вычитания — можно использовать и в качестве унарной операции (т.е. операции, которая принимает один аргумент, или операнд) для указания отрицательных чисел. Например, $а = -1;
Следует обратить внимание, что арифметические операции обычно применяются к целым числам или значениям с двойной точностью. В случае применения их к строкам РНР все же попытается их выполнить, преобразуя строки в числа. При наличии символов "е" или "Е" строка преобразуется в значение двойной точности. В противном случае она преобразуется в целочисленное значение. РНР выполняет поиск цифр в начале строки и найденные цифры использует в качестве значения; если строка не содержит цифр, ее значением будет нуль.
Строковые операции
Мы уже встречали и использовали одну строковую операцию. Операцию конкатенации строк можно использовать для сложения двух строк и генерации и сохранения результата во многом подобно применению операции сложения для получения суммы двух чисел.
$а = "ОАО ";
$b = "Школьник";
$result = $a.$b;
Теперь переменная $result содержит строку "ОАО Школьник".
Операции присваивания
Мы уже знакомы с операцией =, основной операцией присваивания. Этот символ всегда означает операцию присваивания и читается как "устанавливается равным". Например, $totalqty = 0;
$b = 6 + ($а = 5); В результате значение переменной $b устанавливается равным 11. Это справедливо для всех операторов присваивания: значением всего оператора присваивания является значение, присвоенное левому операнду.
При оценке значения выражения скобки применяются с целью повышения приоритета подвыражения, как это делалось в приведенном примере. Скобки работают точно так же, как и в математике.
Кроме простых операций присваивания существует набор комбинированных операций присваивания. Каждая из них представляет собой сокращенную форму записи какой-либо другой операции с переменной и присвоения результата этой переменной.
Например $а += 5; Это эквивалентно записи $а = $а + 5;
Объединенные операции присваивания существуют для каждой из арифметических операций и для операции конкатенации строк.
Операции префиксного и суффиксного инкремента (++) и декремента (—) аналогичны операциям += и -=, но с несколькими отличиями.
Все операции инкремента оказывают двойное, действие — они увеличивают и присваивают значение.
++$a; $a++;
используется операция префиксного инкремента, называемая так потому, что символ ++ записывается перед $а. В результате сначала значение $а увеличивается на 1, а затем возвращается увеличенное значение. В данном случае значение $а увеличивается до 5, а затем 5 возвращается и выводится. Значением всего этого выражения будет 5.
Однако, если символ ++ записывается после $а, используется операция суффиксного инкремента, которая приводит к другому результату. В этом случае действия выполняются в обратном порядке. То есть, вначале значение $а возвращается и выводится, а затем увеличивается на 1. Значением всего этого выражения является 4. Именно это значение и будет выведено. Однако после выполнения этого оператора значение переменной $а равно 5.
Несложно догадаться, что операция — действует аналогично, только здесь значение $а уменьшается на 1, а не увеличивается.
Ссылки
операция ссылки & (амперсанд), которая может использоваться в сочетании с операцией присваивания. Обычно, когда переменная присваивается другой переменной, создается копия первой переменной, которая сохраняется где-либо в памяти. Например, $а = 5; $Ь = $а;
Эти строки кода создают вторую копию значения $а и сохраняют ее в переменной $Ь. Если впоследствии значение $а изменить, значение $Ь не изменится.
Создания копии можно избежать, используя операцию ссылки &, например: $а = 5; $Ь = &$а;
Операции сравнения
Операции сравнения используются для сравнения двух значений. Выражения, в которых используются эти операции, возвращают в зависимости от результата сравнения логические значения true (истинно) или false (ложно).
Операция равенства == (два знака равенства) позволяет проверить равенство двух значений. Например, выражение $а == $Ь можно было использовать для проверки равенства значений, хранящихся в переменных $а и $Ь. Результатом этого выражения будет true, если они равны, или false, если они не равны.
Эту операцию легко спутать с операцией присваивания. Это не приведет к выводу сообщения об ошибке, но в общем случае не даст желаемого результата. В общем случае ненулевые значения интерпретируются как true, а нулевые — как false.
РНР поддерживает также ряд других операций сравнения, которые перечислены в табл. 1.3.
Таблица 1.3 Операции сравнения РНР
Символ операции Название Использование
= равно $а == $b
== идентично $а === $b
!= не равно $а != $b
<> не равно $а <> $b
< меньше $а < $b
> больше $а > $b
<= меньше или равно $а <= $b
>= больше или равно $а >= $b
Следует обратить внимание на операцию идентичности, которая возвращает значение true только в том случае, если оба операнда равны и имеют один и тот же тип.
Логические операции
Логические операции используются для объединения результатов логических условий. Например, нас может интересовать случай, когда значение переменной $а находится в диапазоне между 0 и 100. В этом случае следовало бы проверить условия $а >=0 и $а <= 100, используя операцию AND (И), как в следующем примере:
$а >= 0 && $а <=100
РНР поддерживает логические операции AND (И), OR (ИЛИ), XOR (исключающее ИЛИ) и NOT (HE).
Перечень логических операций и описание их применения приводится в табл. 1.4.
Операции and и ог обладают меньшим приоритетом, нежели операции && и ||.
Поразрядные операции
Поразрядные операции позволяют обрабатывать целые числа как последовательности представляющих их разрядов.
Другие операции
Помимо описанных, существует также ряд других операций. Символ запятой (,) используется для разделения аргументов функций и элементов других списков. Обычно он применяется по мере необходимости.
Две специальных операции new и -> используются, соответственно, для создания экземпляра класса и для доступа к членам класса. Операции работы с массивами [] позволяют получить доступ к элементам массива. Существуют еще три операции.
Тернарная операция
Эта операция, ?:, работает точно так же, как в С. Она записывается в форме
условие ? значение, если условие истинно : значение, если условие ложно
Тернарная операция аналогична исследуемому далее в главе оператору if-else, записанному в виде выражения.
Операция подавления ошибки
Операция подавления ошибки @ может использоваться перед любым выражением, т.е. любой записью, которая генерирует или имеет значение.
Например, $а = @(57/0);
Без символа операции @ эта строка будет генерировать предупреждение о делении на нуль. При использовании операции @ вывод сообщения об ошибке подавляется. При таком подавлении сообщений об ошибках необходимо создать некоторый код обработки ошибок с целью проверки на предмет генерации предупреждений. Если РНР установлен с активизированной функцией track_errors, сообщение об ошибке будет сохраняться в глобальной переменой $php_errormsg.
Операция запуска на выполнение
В действительности символ операции выполнения представляет собой пару символов операций — пару обратных одинарных кавычек (``). Их не следует путать с одинарными кавычками — обычно они вводятся нажатием той же клавиши, что и символ ~ (тильда).
Все, введенное между обратными одинарными кавычками, РНР будет пытаться запустить как команду, вводимую в командной строке сервера. Вывод команды будет значением выражения.
Например, в среде UNIX-подобных операционных систем можно использовать
$out = `ls -la';
echo "<pre>".$out."</pre>";
На сервере Windows этим строкам эквивалентны строки
$out = `dir с: ' ;
echo "<pre>".$out."</pre>";
Любая из версий этого кода получит листинг каталога и сохранит его в переменной $out. Затем его можно вывести в окне браузера или обработать любым требуемым образом.
Использование операций: вычисление итога по форме
Теперь, когда читатели узнали, как использовать операции РНР, можно вычислить итоговую сумму и налог для формы заказа компании «Школьник».
Для этого в нижнюю часть сценария РНР потребуется добавить следующий код:
$totalqty = $copybook + $pencil + $pen;
$totalamount = $copybook * copybookPRICE + $pencil* pencilPRICE + $pen* penPRICE;
$totalamount = number_format($totalamount, 2);
echo "<br>\n";
echo "Заказано: ".$totalqty."<br>\n";
echo "На сумму: ".$totalamount." Руб.<br>\n";
$taxrate =0.1; // местный налог с продаж составляет 10%
$totalamount = $totalamount * (1 + $taxrate);
$totalamount = number_format($totalamount, 2) ;
echo "Вкючая налог: ".$totalamount." Руб,<br>\n";
при помощи функции number_format() выполнялось форматирование итоговых сумм в виде строк с двумя десятичными знаками. Эта функция входит в состав библиотеки математических функций РНР.
Приоритет и ассоциативность: вычисление выражений
В общем случае операции обладают приоритетами, или порядком их вычислений. Кроме того, операциям присуща ассоциативность, определяющая порядок выполнения операций с одинаковым приоритетом. В общем случае операции могут выполняться слева направо, справа налево, либо же их порядок не имеет значения.
В этой таблице операции, имеющие самый низкий приоритет, приводятся в верхней части, а приоритеты возрастают сверху вниз. Обратите внимание, что наивысшим приоритетом обладает операция, которую мы еще не рассматривали: старые добрые круглые скобки. Они повышают приоритет любого заключенного в них выражения. Именно с их помощью в случае необходимости можно изменять правила приоритета.
В выражении можно использовать любое требуемое количество наборов круглых скобок. При этом первым будет вычисляться выражение, заключенное в самые внутренние скобки.
Функции для работы с переменными
Проверка и установка типов переменных
Большинство из этих функций связано с проверкой типов. Двумя наиболее общими функциями являются gettype() и settype(). Они имеют следующие прототипы, определяющие ожидаемые аргументы и возвращаемые значения.
string gettype(mixed var);
int settype(string var, string type);
При вызове функции gettype() ей необходимо передать переменную. Функция определяет тип переменой и возвращает строку, содержащую имя типа или "unknown type", если тип переменной не является одним из стандартных типов: integer, double, string, array или object.
При вызове функции settype() ей необходимо передать переменную, тип которой требуется изменить, и строку, содержащую новый тип переменной из приведенного ранее списка.
Пример применения этих функций показан ниже:
$а = 56;
echo gettype($а)."<br>";
settype ($a, "double");
echo gettype($a)."<br>";
Перед первым вызовом функции gettype() переменная $а имеет тип integer. После вызова функции settype() ее тип изменится на double.
РНР предоставляет также ряд функций проверки типов. Каждая из этих функций принимает переменную в качестве аргумента и возвращает значение true или false. Вот их перечень:
• is_array()
• is_double(), is_float(), is_real() (Это одна и та же функция)
• is_long(), is_int(), is_integer() (Это одна и та же функция)
• is_string()
• is_object()
Проверка состояния переменных РНР имеет несколько функций, предназначенных для проверки состояния переменных. Первая из них — isset(), имеющая следующий прототип:
int isset(mixed var);
Эта функция принимает в качестве аргумента имя переменной и возвращает значение true, если переменная существует, и false в противном случае.
Переменную можно удалить, используя сопутствующую функцию unset(). Она имеет следующий прототип:
int unset(mixed var);
Эта функция удаляет переменную и возвращает значение true.
И наконец, существует функция empty(). Она проверяет существование переменной и наличие у нее непустого, ненулевого значения, возвращая, соответственно, значение true или false. Эта функция имеет следующий прототип:
int empty(mixed var);
Рассмотрим пример использования этих трех функций.
echo isset($copybook);
echo isset($nothere);
echo empty($copybook);
echo empty($nothere);
Функция isset() должна возвращать для переменной $copybook значение true вне зависимости от того, введено или нет значение в поле формы. Возвращаемое значение функции empty() зависит от введенного значения.
Переменная Snothere не существует, поэтому для нее функция isset() будет генерировать значение false, а функция empty() — true. Эти функции могут оказаться полезными при проверке заполнения пользователем соответствующих полей формы.
Повторная интерпретация переменных
Можно достичь эффекта, эквивалентного приведению переменной, при помощи функции. Для этого применяются три функции:
int intval(mixed var);
double doubleval(mixed var);
string strval(mixed var);
Каждая из них принимает в качестве аргумента переменную и возвращает значение переменной, преобразованное к соответствующему типу.
Управляющие структуры — это языковые структуры, которые позволяют управлять потоком выполнения программы или сценария. Их можно разделить на условные структуры (или структуры ветвления) и структуры повторения, или циклы. Далее рассматриваются характерные реализации каждого вида структур в РНР.
Принятие решений с помощью условных операторов
Дабы обеспечить своевременную реакцию на вводимую пользователем информацию, код должен быть в состоянии принимать решения. Конструкции, которые указывают программе о необходимости принятия решений, называются условными операторами.
Оператор if
if( $totalqty == 0 )
echo "Вы ничего не заказали!<br>";
Часто внутри такого условного оператора, как if, требуется выполнить более одного оператора. Последовательность операторов можно сгруппировать в блок. Для объявления блока операторы должны помещаться в фигурные скобки:
if( $totalqty == 0 )
{
echo "<font color=red>";
echo " Вы ничего не заказали!<br>";
echo "</font>";
}
Операторы else
Часто требуется принимать решение не только о выполнении того или иного действия, но и выбирать определенный набор возможных действий в противном случае. Оператор else позволяет определить альтернативное действие, которое должно выполняться, если значением условия в операторе if окажется false. В рассматриваемом примере необходимо предупреждать клиентов, когда они ничего не заказывают. С другой стороны, если они делают заказ, вместо предупреждения требуется вывести список заказанного.
Если немного изменить код и добавить в него оператор else, можно отображать либо предупреждение, либо итоговую информацию.
if( $totalqty = 0 )
{
echo "You did not order anything on the previous page!<br>";
>
else
{
echo $tireqty." tires<br>";
echo $oilqty." bottles of oil<br>";
echo $sparkqty." spark plugs<br>";
}
Вкладывая операторы if один в другой, можно строить более сложные логические процессы. Следующий код не только обеспечит отображение итоговой информации, когда значение условия Stotalqty == 0 равно true, но и отображение каждой из итоговых строк только при выполнении ее собственного условия.
if( $totalqty = 0)
{
echo "You did not order anything on the previous page!<br>";
}
else
{
if ( $tireqty>0 )
echo $tireqty." tires<br>";
if ( $oilqty>0 )
echo $oilqty." bottles of oil<br>";
if ( $sparkqty>0 )
echo $sparkqty." spark plugs<br>";
}
Операторы elseif
Для многих принимаемых решений может существовать более двух возможностей. Последовательность множества вариантов действий создается с использованием оператора elseif, который представляет собой комбинацию операторов else и if. При наличии последовательности условий программа может проверять каждое из них до тех пор, пока не отыщет то, значением которого является true. Боб предоставляет скидки при заказе большого количества автопокрышек. Схема скидок выглядит следующим образом:
• Приобретение менее 10 автопокрышек — без скидки
• Приобретение 10-49 автопокрышек — скидка 5%
• Приобретение 50-99 автопокрышек — скидка 10%
• Приобретение 100 и более автопокрышек — скидка 15%
Можно создать код для вычисления скидок с использованием условий и операторов if и elseif. Для объединения двух условий в одно применяется операция И (&&).
if( $tireqty < 10 )
$discount = 0;
elseif ( $tireqty >= 10 &S $tireqty <= 49 )
$discount = 5;
elseif ( $tireqty >= 50 SS $tireqty <= 99 )
$discount = 10;
elseif( $tireqty > 100 )
$discount = 15;
Обратите внимание, что можно применять как elseif, так и else if — оба варианта правильны. При использовании каскадных наборов операторов elseif следует помнить, что будет выполняться только один из блоков операторов. В данном примере это не важно, поскольку все условия являются взаимоисключающими — в каждый момент времени может выполняться только одно из них. Если бы условия были записаны так, что одновременно могло бы выполняться несколько условий, выполнялся бы только блок или оператор, следующий за первым истинным условием.
Операторы switch
Оператор switch работает аналогично оператору if, но позволяет условному выражению иметь в качестве результата более двух значений. В операторе if условие принимает значение true или false. В операторе switch условие может принимать любое количество различных значений до тех пор, пока оно имеет простой тип (integer, string или double). Для обработки каждого из значений, на которые требуется реагировать, необходимо записать оператор case, а также (необязательно) можно определить случай для обработки по умолчанию любых значений, для которых специально не задан оператор case. Боб желает знать, какие формы рекламы работают на него наиболее эффективно. Для этого в форму заказа можно добавить вопрос. Добавьте в форму следующий HTML-код, после чего она должна выглядеть так, как показано на рис. 1.6:
<tr>
<td>How did you find Bob's</td>
<tdxselect name="find">
<option value = "a">I'm a regular customer
<option value = "b">TV advertising
<option value = "c">Phone directory
<option value = "d">Word of mouth
</select>
</td>
</tr>
Приведенный HTML-код добавил новую переменную формы, значением которой будет "а", "Ь", "с" или "d". Эту новую переменную можно было бы обработать с помощью последовательности операторов if и elseif:
if($find == "a")
echo "<P>Regular customer.";
elseif($find == "b")
echo "<P>Customer referred by TV advert.";
elseif($find == "c")
echo "<P>Customer referred by phone directory.";
elseif($find == "d")
echo "<P>Customer referred by word of mouth.";
Либо же можно было бы записать оператор switch:
switch($find)
case "a" :
echo "<P>Regular customer.";
break;
case "b" :
echo "<P>Customer referred by TV advert.";
break;
case "c" :
echo "<P>Customer referred by phone directory.";
break;
case "c" :
echo "<P>Customer referred by word of mouth.";
break;
default :
echo "<P>We do not know how this customer found us." ;
break;
Этот оператор switch ведет себя несколько иначе, нежели оператор if или elseif. Оператор if оказывает влияние только на один оператор, если только специально не использовать фигурные скобки для создания блока операторов. Оператор switch действует по-другому. Когда оператор case в операторе switch активизируется, операторы выполняются до тех пор, пока не встретится оператор break. Без него оператор switch выполнял бы весь код, следующий за оператором case, условие которого было истинным. При достижении оператора break будет выполняться строка кода, следующая за оператором switch.
Сравнение различных условных операторов
У читателей, не знакомых с этими операторами, может возникнуть вопрос "Какой же из них наилучший?". На этот вопрос невозможно дать однозначный ответ. Один или несколько операторов else, elseif или switch не позволяют сделать ничего такого, чего нельзя было бы сделать с помощью набора операторов if. В каждой конкретной ситуации следует использовать именно те условные операторы, которые выглядят наиболее читабельно. Утверждение станет более понятным по мере приобретения практического опыта.
Итерация: повторение действий
Одна из задач, с которыми компьютеры всегда справлялись очень успешно — автоматизация повторяющихся действий. Если что-то требуется выполнять многократно и одинаково, для повторения определенных частей программы стоит применить цикл.
Циклы while
Простейший вид цикла в РНР — цикл while. Подобно оператору if, этот оператор основан на проверке условия. Различие между циклом while и оператором if состоит в том, что если условие принимает значение true, оператор if выполняет следующий за ним блок кода только один раз. Цикл while выполняет блок операторов многократно до тех пор, пока условие принимает значение true.
В общем случае цикл while используется, когда не известно, сколько итераций потребуется для выполнения условия. Если же требуется фиксированное количество итераций, стоит подумать об использовании цикла for. Основная структура цикла while имеет вид while( условие ) выражение;
Следующий цикл while отображает числа от 1 до 5.
$num = 1;
while ($num <= 5 )
{
echo $num. "<BR>" ;
$num++;
Условие проверяется в начале каждой итерации. Если оно принимает значение false, блок не будет выполняться и цикл завершается. После этого выполняется оператор, следующий за циклом.
В листинге 1.4 цикл while используется для генерации таблицы стоимости доставки.
Листинг 1.4 freightphp — генерация таблицы стоимости доставки компании Боба с
помощью РНР
<body>
<table border = 0 cellpadding = 3>
<tr>
<td bgcolor = "#CCCCCC" align = oenter>Distance</td>
<td bgcolor = "#CCCCCC" align = center>Cost</td>
</tr>
<?
$distance = 50;
while ($distance <= 250 )
{
echo "<tr>\n <td align = right>$distance</td>\n";
echo " <td align = right>". $distance / 10 ."</td>\n</tr>\n";
$distance += 50;
)
?>
</table>
</body>
</html>
Циклы for
Описанный выше способ использования циклов while очень распространен. Сначала устанавливается начальное значение счетчика. Перед каждой итерацией значение счетчика проверяется в условии. В конце каждой итерации значение счетчика изменяется. При помощи цикла for такого рода цикл можно записать в более компактной форме.
Основная структура цикла for имеет вид
for( выражение!; условие; выражение^)
выражение:?;
• выражение! выполняется один раз в начале цикла. Обычно в нем устанавливается начальное значение счетчика.
• Выражение условие проверяется перед каждой итерацией. Если выражение возвращает значение false, итерация прекращается. Обычно в нем значение счетчика сравнивается с предельным значением.
• выражение2 выполняется в конце каждой итерации. Обычно в нем изменяется значение счетчика.
• выражениеЗ выполняется один раз для каждой итерации. Обычно это выражение представляет собой блок кода и содержит собственно тело цикла.
Пример цикла while, приведенный в листинге 1.4, можно переписать с применением цикла for. PHP-код примет следующий вид:
<?
for ($distance = 50; $distance <= 250; $distance += 50)
{
echo "<tr>\n <td align = right>$distance</td>\n";
echo " <td align = right>". $distance / 10 ."</td>\n</tr>\n";
Попутно отметим, что можно объединять переменные переменных и циклы for для организации итераций по последовательности повторяющихся полей формы. Например, при наличии полей формы с именами наподобие name I, nameZ, патеЗ и т.д. их можно обрабатывать следующим образом:
for ($i=l; $1 <= $numnames; $i++)
{
$temp= "name$i";
echo $$temp."<br>"; // любая требуемая обработка
}
Динамически создавая имена переменных, можно обращаться к каждому из полей по очереди.
Циклы do..while
Последний тип циклов, который мы рассмотрим, действует несколько иначе. Общая структура оператора do..while имеет вид
do
выражение;
while( условие );
Цикл do..while отличается от цикла while тем, что в нем условие проверяется в конце. Это означает, что в цикле do..while оператор или блок внутри цикла выполняется всегда не менее одного раза. Даже в этом примере, в котором с самого начала условие имеет значение false и никогда не может принять значение true, цикл выполнится один раз, прежде чем условие будет проверено и цикл завершится.
$num = 100;
do
<
echo $num."<BR>";
}
while ($num < 1 ) ;
Выход из управляющей структуры или сценария
В зависимости от эффекта, который требуется получить, для выхода из фрагмента кода можно воспользоваться одним из трех подходов. Если необходимо прекратить выполнение цикла, можно задействовать оператор break, как было описано ранее в разделе, посвященном оператору switch. При использовании оператора break в цикле выполнение сценария будет продолжаться, начиная со строки сценария, следующей за циклом. Если требуется перейти к следующей итерации цикла, можно воспользоваться оператором continue.
Если требуется завершить выполнение всего PHP-сценария, необходимо применить оператор exit. Обычно этот оператор используется при проверке на ошибки. Например, ранее приведенный пример можно было бы изменить следующим образом:
if( $totalqty = 0 >
{
echo "You did not order anything on the previous page!<br>";
exit;
}
Вызов оператора exit прекращает выполнение оставшейся части PHP-сценария.
Существуют два основных способа хранения данных: в текстовых файлах и в базах данных.
Запись данных в файл реализуется в три шага:
1. Открытие файла. Если файл еще не существует, его потребуется создать.
2. Запись данных в файл.
3. Закрытие файла.
Аналогично, считывание данных из файла также связано с выполнением трех шагов:
1. Открытие файла. Если файл не может быть открыт (например, он не существует), эта ситуация должна быть распознана и следует предусмотреть корректный выход из нее.
2. Считывание данных из файла.
3. Закрытие файла.
При необходимости считывания данных из файла можно выбирать, какая часть файла должна считываться за один раз.
Для открытия файла в среде РНР используется функция fopen(). При открытии файла необходимо указать режим открытия файла.
При открытии файла следует принять три решения:
1. Файл можно открыть только для чтения, только для записи или для чтения и записи.
2. При выполнении записи в файл можно перезаписать любое существующее содержимое файла либо же дописать новые данные в конец файла.
3. При попытке выполнения записи в файл в системе, которая различает двоичные и текстовые файлы, может потребоваться указать тип файла.
Функция fopen() поддерживает любые имеющие смысл комбинации этих трех вариантов.
Использование функции fopen() для открытия файла
файл можно открыть для записи с помощью следующего оператора:
$fp = fopen("$DOCHMENT_ROOT/../orders/orders.txt", "w');
Функция fopen ожидает двух или трех входных параметров. Обычно используются два параметра, как показано в приведенной выше строке кода. Первым параметром должен быть файл, который необходимо открыть. При этом можно указать путь к файлу, как было сделано в приведенной выше строке кода - orders.txt находится в каталоге orders. Мы использовали встроенную переменную $DOCUMENT_ROOT PHP. Эта переменная указывает на основание дерева документов Web-сервера. Кроме того, мы использовали символ "..", означающий "родительский каталог каталога $DOCUMENT_ROOT. В целях повышения безопасности этот каталог находится вне дерева документов. Нежелательно, чтобы этот файл был доступен в Web помимо предоставляемого нами интерфейса. Этот путь называется относительным, поскольку он описывает позицию в файловой системе относительно $DOCUMENT_ROOT.
Можно было бы задать и абсолютный путь к файлу — путь от корневого каталога (/ в системе UNIX и, как правило, С:\ в системе Windows). На сервере UNIX, который используют авторы, такой путь выглядит как /home/book/orders. Проблема, связанная с подобным указанием пути, особенно в случае размещения своего сайта на чужом сервере, заключается в том, что абсолютный путь может изменяться. Мы убедились в этом на собственном горьком опыте после того, как пришлось изменять абсолютные пути в большом количестве сценариев, когда системные администраторы без предупреждения "сочли необходимым" изменить структуру каталогов.
Если путь вообще не указан, файл будет создаваться или отыскиваться в том же каталоге, в котором находится собственно сценарий. Упомянутое поведение будет иным при запуске РНР через какую-то CGI-оболочку и зависит от конфигурации сервера.
В среде UNIX в качестве разделителя каталогов используется символ прямой (с уклоном вправо) косой черты (/). На платформах Windows можно применять символы прямой или обратной косой черты. При использовании символа обратной черты они должны быть помечены как специальные (т.е. отменены), чтобы функция fopen смогла их корректно интерпретировать. Для отмены перед символом следует просто поместить дополнительный символ обратной косой черты, как показано в следующей строке:
$fp = fopen("..\\..\\orders\\orders.txt", "w") ;
Второй параметр функции fopen() — это режим файла, который должен иметь строковый тип. Этот параметр определяет, что необходимо делать с файлом. В данном случае в функцию fopen() передается параметр "w" — это означает открытие файла для записи.
Третий параметр функции fopen() не является обязательным. Его можно использовать, если файл необходимо искать в пути include_path (определенном в конфигурации РНР). Если это требуется, установите параметр равным 1. В этом случае не следует задавать имя каталога или путь:
$fp = fopen("orders, txt" , "a", 1);
В случае успешного открытия файла функция fopen() возвращает указатель на файл и сохраняет его в переменой, в данном случае $1р. Эта переменная будет использоваться для доступа к файлу, когда из него потребуется выполнить считывание либо что-то записать в него.
Открытие удаленных файлов через FTP или HTTP
Используя функцию fopen(), можно открывать для чтения или записи не только локальные файлы, но и удаленные с использованием протоколов FTP и HTTP. Если используемое имя файла начинается с ftp://, открывается FTP-соединение с указанным сервером в пассивном режиме и возвращается указатель на начало файла. Если используемое имя файла начинается с http://, открывается HTTP-соединение с указанным сервером и возвращается указатель на ответ от сервера. В случае применения режима HTTP обязательно следует указывать завершающие символы косой черты в именах каталогов, как показано в следующем примере:
http://www.server.com/, но не http://www.server.com
При второй форме указания адреса (без завершающей косой черты) Web-сервер, как правило, будет использовать перенаправление HTTP с целью обращения по первому адресу (с косой чертой). Проверьте это в своем браузере.
Функция fopen() не поддерживает перенаправление HTTP, поэтому необходимо указывать URL-адреса, которые ссылаются на каталоги с завершающими символами косой черты. Помните, что имена доменов в URL-адресах не зависят от регистра, однако пути и имена файлов зависят. Обычная ошибка, связанная с открытием файла — попытка открыть файл, для которого отсутствуют права на чтение или запись. В этом случае РНР выводит соответствующее предупреждение.
Если обращение к функции fopen() оказывается безуспешным, функция возвращает значение false. Обработку ошибок можно сделать более удобной для пользователя, подавив сообщение об ошибке от РНР (операция @) и реализовав собственное сообщение.
Запись в файл в РНР выполняется сравнительно просто. Для этого можно воспользоваться любой из функций fwrite() (file write — запись в файл) или fputs() (file put string — запись строки в файл); fputs() — это псевдоним функции fwrite(). Функцию fwrite() можно вызвать следующим образом:
fwrite($fp, $outputstring);
В действительности функция fwrite() принимает три параметра, однако третий из них не является обязательным. Прототип функции fwrite() имеет следующий вид
int fputs(int fp, string str, int [length]);
Третий параметр length представляет собой максимальное количество байтов, которые требуется записать. При передаче этого параметра функция fwrite() будет записывать строку str в файл, указанный параметром fp, пока не встретит конец строки или не запишет length байтов, в зависимости от того, что произойдет раньше. По завершении использования файла его следует закрыть при помощи функции fclose(), как показано ниже:
fclose($fp);
Эта функция возвращает значение true в случае успешного закрытия файла и false, если файл не был закрыт. Ошибка при этом значительно менее вероятна, чем при открытии файла, поэтому в данном случае проверка выполнения функции не выполняется. Проверка на наличие конца файла осуществляется при помощи функции feof():
while (!feof($fp))
Построчное считывание: fgets(), fgetss() и fgetcsv()
для считывания из файла используется функция fgets():
$order= fgets($fp, 100);
Эта функция используется для считывания из файла по одной строке за один раз. В данном случае считывание будет выполняться до тех пор, пока не встретится символ новой строки (\n), EOF или из файла не будут прочитаны 99 байт. Максимальная длина считываемой строки равна указанной длине минус один байт. Существует много различных функций, которые используют для считывания из файлов. Функция fgets() полезна при работе с файлами, содержащими обычный текст, который требуется обрабатывать по кускам.
Интересным вариантом функции fgets() является функция fgetss(), имеющая следующий прототип:
string fgetss(int fp, int length, string [allowable_tags]) ;
Эта функция во многом подобна функции fgetsQ за исключением того, что она будет избавляться от любых дескрипторов РНР и HTML, найденных в строке. Если в файле необходимо оставить конкретные дескрипторы, они должны быть включены в строку allowable_tags. Функцию fgetss() следует использовать для обеспечения безопасности при считывании файла, записанного кем-либо другим или содержащего данные, введенные пользователем. Отсутствие ограничений на наличие в файле HTML-кода может привести к нарушению тщательно спланированного форматирования. Отсутствие ограничений на наличие в файле PHP-кода может предоставить злонамеренному пользователю почти полную свободу действий на сервере.
Функция fgetcsv() — еще одна вариация функции fgets(). Она имеет следующий прототип:
array fgetcsv(int fp, int length, string [delimiter]);
Эта функция используется для разделения строк файлов при использовании в качестве разделительного символа табуляции, как предлагалось ранее, или запятой, которая обычно применяется в электронных таблицах и других приложениях. Если требуется восстановить переменные заказа отдельно одна от другой, а не в виде строки текста, следует прибегнуть к функции fgetcsv(). Она вызывается подобно функции fgets(), но ей необходимо передать разделитель, используемый для разделения полей.
Например, $order = fgetcsv($fp, 100 " \ t " ) ;
получает строку из файла и разбивает ее при каждом обнаружении символа табуляции (\t). Результирующие данные помещаются в массив (в этом примере — в Sorder). Параметр length должен быть больше длины самой длинной строки считываемого файла, выраженной в символах.
Считывание всего файла: readfile(), fpassthru(), file()
Вместо считывания по одной строке из файла за один проход можно считывать весь файл. Существуют три различных способа. Первый заключается в использовании функции readffle(). Весь ранее созданный сценарий можно заменить одной строкой:
readfile("$DOCUMENT_ROOT/../orders/orders.txt");
Функция readfile() открывает файл, повторяет его содержимое в стандартном выводе (окне браузера), а затем закрывает файл. Прототип этой функции имеет вид
int readfile (string имя_файла, int [use_include_path]) ;
Необязательный второй параметр указывает, должен ли РНР искать файл в пути use_include_path, и действует так же, как в функции fopen(). Функция возвращает общее количество байтов, считанных из файла. Во-вторых, можно использовать функцию fpassthru(). Вначале необходимо открыть файл с помощью функции fopen(). Затем указатель файла можно передать в функцию fpassthru(), которая загрузит содержимое файла, начиная с позиции, заданной указателем, в стандартный вывод. По завершении этого процесса функция закрывает файл. Ранее приведенный сценарий можно заменить функцией fpassthru() следующим образом:
$fp = fopen("$DOCHMENT_ROOT/../orders/orders.txt", "r");
fpassthru($fp);
Функция fpassthru() возвращает значение true, если считывание было выполнено успешно, и false — в противном случае. Третья возможность считывания всего файла — использование функции file(). Эта функция идентична функции readfile() за исключением того, что вместо повторения файла в стандартном выводе она преобразует его в массив. отметим, что эту функцию следовало бы вызывать так:
$filearray = file($fp);
Эта строка приведет к считыванию всего файла в массив, названный Sfflearray. Каждая строка файла сохраняется в отдельном элементе массива.
Считывание символа: fgetc() Еще одна возможность обработки файлов — считывание из файла по одному символу. Это выполняется с помощью функции fgetc(). В качестве своего единственного параметра она принимает указатель файла и возвращает следующий символ файла.
Цикл while в нашем первоначальном сценарии можно заменить циклом, в котором используется функция fgetc():
while (!feof($£p)){
$char = £getc($fp);
if (!feof<$fp)) echo ($char=="\n" ? "<br>": $char);
}
Используя функцию fgetc(), этот код считывает из файла по одному символу за раз и сохраняет его в переменной Schar, пока не будет достигнут конец файла. Затем выполняется небольшая дополнительная обработка с целью замещения текстовых символов конца строки \п HTML-разделителями строк <Ьг>. Это делается лишь для приведения в порядок форматирования. Поскольку без этого кода браузеры не распознают новые строки, весь файл был бы выведен в виде единой строки. (Попытайтесь сделать это и посмотрите, что получится.) Для выполнения этой задачи используется тернарная операция.
Побочный эффект использования функции fgetc() вместо функции fgets() заключается в том, что она будет возвращать символ EOF, в то время как fgets() не делает этого. После считывания символа приходится снова выполнять проверку с помощью функции feof(), поскольку символ EOF не должен отображаться в окне браузера.
В общем случае считывание файла символ за символом не находит особого применения, если только по какой-либо причине не требуется посимвольная обработка файла.
Считывание строк произвольной длины: fread() Последний способ считывания из файла, который мы рассмотрим — использование функции fread() для считывания из файла произвольного количества байтов. Эта функция имеет следующий прототип:
string £read(int fp, int length);
Функция считывает length байтов или все байты до конца файла, в зависимости от того, что произойдет раньше.
Другие полезные файловые функции
Существует ряд других файловых функций, которые временами могут оказаться полезными.
Проверка существования файла: file_exists()
if (file_exists("$DOCOMENT_ROOT/../orders/orders.txt"))
echo "There are orders waiting to be processed.";
else
echo "There are currently no orders.";
Выяснение размера файла: filesize() возвращает размер файла, выраженный в байтах:
echo filesize("$DOCUMENT_ROOT/../orders/orders.txt");
Эта функция может применяться в сочетании с функцией fread() для одновременного считывания всего файла (или определенной его части). Весь первоначальный сценарий можно заменить следующим кодом:
$fp = fopen("$DOCUMENT_ROOT/../orders/orders.txt", "r");
echo fread( $fp, filesize("$DOCUMENT_ROOT/../orders/orders.txt" )) ;
fclose( $fp ) ;
Удаление файла unlink()
unlink("$DOCOMENT_ROOT/../orders/orders.txt");
Эта функция возвращает значение false, если файл не может быть удален. Как правило, это будет происходить при недостаточном уровне прав доступа к файлу или если файл не существует.
Перемещение внутри файла: rewind(), fseek и ftell()
Выяснять позицию указателя файла внутри файла и изменять ее можно с помощью функций rewind(), fseek() и ftell().
Функция rewind() переустанавливает указатель файла на начало файла. Функция ftell() сообщает в байтах позицию указателя относительно начала файла. Например, в нижнюю часть первоначального сценария (перед командой fclose()) можно добавить следующие строки:
echo "Final position of the file pointer is ". (ftell ($fp));
echo "<br>";
rewind($fp);
echo "After rewind, the position is ". (ftell($fp));
echo "<br>";
Функция fseek() может использоваться для установки указателя файла в некоторую точку внутри файла. Ее прототип имеет вид
int f seek(int fp, int offset);
В результате вызова функции fseek() указатель файла Jp устанавливается в точку файла, имеющую смещение offset байтов относительно начала файла. Вызов функции rewind() эквивалентен вызову функции fseek() со смещением, равным нолю. Например, функцию fseek() можно использовать для нахождения средней записи в файле или для выполнения бинарного поиска. Часто, когда подобные задачи требуется решать применительно к достаточно сложному файлу данных, имеет смысл использовать базу данных.
Блокирование файлов
В РНР блокирование реализуется с помощью функции flock(). Эта функция должна вызываться после открытия файла, но перед считыванием данных из файла или их записью в файл.
Прототип функции flock() выглядит так:
bool flock (int f p , int operation);
В функцию необходимо передать указатель на открытый файл и число, представляющее вид требуемой блокиро-вки. Функция возвращает значение true, если блокировка была успешно выполнена, и false в противном случае.
Если решено использовать функцию flock(), ее следует включить во все сценарии, в которых используется данный файл; в противном случае ее применение лишено смысла.
Использование массивов
Для создания численно индексированного массива можно использовать следующую строку кода:
$products = array( "Tires", "Oil", "Spark Plugs" );
В результате создается массив products, содержащий три заданных значения: "Tires", "Oil" и "Spark Plugs". Значения одного массива можно копировать в другой массив с помощью операции =. Доступ к элементам массива: []
Для автоматического создания возрастающей последовательности можно использовать функцию range(a,b). Следующая строка кода создает массив numbers, содержащий элементы, которые являются числами от 1 до 10:
$numbers = range(1,10) ;
Подобно другим переменным РНР, массивы не нужно инициализировать или создавать заранее. Они автоматически создаются при первом использовании.
В ассоциативным массиве с каждым значением можно связать любой ключ, или индекс.
Создание ассоциативного массива, в котором названия товаров используются в качестве ключей, а их цены — в качестве значений.
$prices = array( "Tires"=>100, "Oil"=>10, "Spark Plugs"=>4 );
Доступ к содержимому ассоциативного массива осуществляется через имя переменной и ключ, поэтому к информации, сохраненной в массиве prices можно обратиться как к
$prices[ "Tires" ], $prices[ "Oil"] и $prices[ "Spark Plugs" ].
Массивы могут создаваться и инициализироваться по одному элементу. Вместо создания массива с неско-лькими элементами создаем массив только с одним элементом, а затем добавляем в него еще несколько.
$prices = array( "Tires"=>100 );
$prices["Oil"] = 10;
$prices["Spark Plugs"] = 4 ;
Ниже приведен еще один, несколько отличающийся от предыдущего, однако эквивалентный ему фрагмент кода. В этой версии массив вообще не создается явно. Он создается при добавлении в него первого элемента.
$prices["Tires"] = 100;
$prices["0il"] = 10;
$prices["Spark Plugs"] =4;
Поскольку в ассоциативном массиве индексы не являются числами, для работы с массивом нельзя использовать простой счетчик в цикле for. Следующий код выводит содержимое нашего массива Sprices:
while( $element = each( $prices ) )
{echo $element[ "key" ];
echo " - ";
echo $element[ "value" ] ;
echo "<br>";}
функция each() возвращает текущий элемент массива и делает текущим следующий элемент. Поскольку функция each() вызывается внутри цикла while, она по очереди возвращает каждый из элементов массива и прекращает свое выполнение по достижении конца массива.
В этом примере кода переменная Selement является массивом. При вызове функции each() она предоставляет массив с четырьмя значениями и четырьмя индексами ячеек массива. Ячейки key и 0 содержат ключ текущего элемента, а ячейки value и 1 — значение текущего элемента. Хотя выбор ячеек не имеет значения, мы использовали именованные ячейки, а не нумерованные.
Это же можно сделать более изящным и привычным способом — использовать функцию Iist() для разделения массива на ряд значений. Два значения, передаваемые функцией each(), можно разделить следующим образом:
$list( $product, $price ) = each( $prices ) ;
Эта строка использует функцию each() для получения текущего элемента из массива Sprices, возвращает его в виде массива и делает следующий элемент текущим. Кроме того, функция list() используется для преобразования элементов 0 и 1 массива, возвращаемого функцией each(), в две новых переменных: Sproduct и Sprice.
Можно циклически просмотреть весь массив Sprises, повторяя его содержимое, воспользовавшись следующим коротким сценарием.
while ( list( $product, $price ) = each( $prices ) )
echo "$product - $price<br>";
При использовании функции each() следует помнить, что массив отслеживает текущий элемент. Если в одном и том же сценарии элемент необходимо использовать дважды, с помощью функции reset() потребуется снова установить текущий элемент на начало массива.
Многомерные массивы
Массив не обязательно должен быть простым списком ключей и значений — каждая ячейка массива может содержать другой массив. Таким образом, можно создать двумерный массив.
$products = array( array( "TIR", "Tires", 100 ),
array( "OIL", "Oil", 10 ),
array( "SPK", "Spark Plugs", 4 ) ) ;
for ( $row = 0; $row < 3; $row++ )
for ( $column = 0; $column < 3; $column++ )
{echo "|".$products[$row][$column];
echo "|<BR>";}
или
$products = array ( array ( Code => "TIE",
Description => "Tires",
price => 100) ,
array ( Code => "OIL" ,
Description => "Oil",
price => 10),
array ( Code => "SPK",
Description => "Spark Plugs",
price =>4));
Однако при этом утрачивается возможность использования простого цикла for для поочередного просмотра всех столбцов. Ниже приведен один из вариантов кода для отображения этого массива:
for ( $row = 0; $row < 3; $row++ )
(while ( list( $key, $value ) = each( $products[ $row ] ) )
{echo " | $ value" ;}
echo "|<BR>";}
Упорядочение массива в алфавитном порядке: функция sort() зависит от регистра, т.е. прописные буквы предшествуют строчным буквам. Так, 'А' меньше 'Z', но 'Z' меньше 'а'.
Функция asort() упорядочивает ассоциативный массив в соответствии со значениями элементов. В данном массиве значения — это цены, а ключи — текстовые описания. Если сортировку нужно выполнить не по ценам, а по описаниям, следует использовать функцию ksort(), которая выполняет сортировку не по значениям, а по ключам.
Обратные функции — rsort(), arsort() и krsort().
Функция shuffle() располагает элементы массива в случайном порядке. Функция array_reverse() возвращает копию массива, в которой все элементы располагаются в обратном порядке.
Функция count() для выяснения количества элементов в массиве.
Функция explode() для разбиения каждой строки, чтобы перед выводом ее можно было подвернуть определенной обработке и форматированию. Функция explode имеет следующий прототип:
array explode(string разделитель, string строка)
Ранее уже упоминалось, что каждый массив имеет внутренний указатель, который указывает на текущий элемент массива. Ранее мы косвенно задействовали этот указатель при использовании функции each(), но его можно использовать и манипулировать им непосредственно.
При создании нового массива текущий указатель инициализируется так, чтобы указывать на первый элемент массива. Вызов функции current( $array_name ) возвращает первый элемент.
Вызов функции next() или each() перемещает указатель вперед на один элемент.
Вызов функции each($array_name) возвращает текущий элемент, прежде чем переместить указатель. Функция next() ведет себя несколько иначе — вызов функции next($array_name) приводит к перемещению указателя, а затем к возврату нового текущего элемента.
Функция reset() возвращает указатель на первый элемент массива. Аналогично, вызов функции end($array_name) перемещает указатель в конец массива. Функции reset() и end() возвращают, соответственно, первый и последний элементы массива.
Для перемещения в массиве в обратном направлении можно воспользоваться функциями end() и prev(). Функция prev() является обратной по отношению к функции next(). Она перемещает текущий указатель на один элемент назад, а затем возвращает новый текущий элемент.
Иногда требуется выполнять одинаковые действия по отношению ко всем элементам массива или изменять их одинаковым образом. Делать это позволяет функция array_walk. Функция array_walk() имеет следующий прототип:
int array_walk(array arr, string func, [mixed userdata])
Как видите, функция array_walk() принимает три параметра. Первый, arr — массив, который должен быть обработан. Второй, func — имя определяемой пользователем функции, которая будет применяться к каждому элементу массива. Третий параметр, userdata, является необязательным. В случае его использования он будет передан определяемой пользователем функции в качестве параметра. Удобной определяемой пользователем функцией может оказаться функция, которая отображает каждый элемент в определенном формате.
Следующий фрагмент кода отображает каждый элемент в новой строке, вызывая определяемую пользователем функцию myPrint() с каждым элементом массива Sarray:
function myPrint($value)
{echo "$value<BR>";}
array_walk($array, myPrint);
Создаваемая функция должна иметь конкретную сигнатуру. Для каждого элемента массива функция array_walk принимает ключ и значение, хранящиеся в массиве, и любые данные, переданные в параметре userdata, после чего вызывает функцию пользователя, подобную следующей:
Yourfunction(значение, ключ, userdata)
В большинстве случаев определяемая пользователем функция будет использовать только хранящиеся в массиве значения. В некоторых случаях функции нужно будет передать параметр через userdata. Иногда наряду со значением интерес может представлять и ключ каждого элемента. Но в общем случае функция может игнорировать ключ и параметр userdata, как это имеет место в функции MyPrint().
В качестве несколько более сложного примера создадим функцию, которая изменяет значения в массиве и требует передачи ей параметра. Обратите внимание, что хотя сам по себе ключ не представляет интереса, функция должна принять его, чтобы принять третий параметр.
function myMultiply(&$value, $key, $factor)
{$value *= $factor;}
array_walk(&$array, "myMultiply", 3);
В этом примере мы определяем функцию myMultiply(), которая будет умножать каждый элемент массива на указанный коэффициент. В данном случае необходимо использовать необязательный третий параметр функции array_walk(), чтобы она передала его в функцию MyMultiply() в качестве коэффициента умножения. В связи с этим функцию myMultiplyO необходимо определить так, чтобы она принимала три параметра - значение элемента массива (Svalue), ключ элемента массива (Skey) и параметр коэффициента умножения (Sfactor). Ключ функция игнорирует. Следует отметить способ передачи параметра Svalue. Символ амперсанда (&) перед именем переменной в определении функции myMultiplyO означает, что $value будет передаваться по ссылке. Передача по ссылке позволяет функции изменять содержимое массива.
Преобразование массивов в скалярные переменные: функция extractQ При наличии ассоциативного массива, содержащего ряд пар ключ-значение, с помощью функции extract() его можно преобразовать в набор скалярных переменных. Эта функция имеет следующий прототип:
extract (array var_array [, int extraot_type] [, string prefix] );
Функция extract() предназначена для создания скалярных переменных, имеющих те же имена, что и у ключей массива. Переменным присваиваются значения, равные значениям, которые хранятся в массиве.
Манипулирование строками и регулярные выражения
функция mail() отправляет сообщение электронной почты. Ее прототип выглядит следующим образом:
bool mail(string кому, string тема, string сообщение, string [доаолнителънае_заголовкк]
Первых три параметра обязательны и представляют, соответственно, адрес, по которому должно быть отправлено сообщение, строку темы и содержимое сообщения. Четвертый параметр может использоваться для отправки любых дополнительных допустимых заголовков сообщения электронной почты. Эти заголовки описаны в документе RFC822, который доступен в Internet.
Функция trim() удаляет пробелы в начале и конце строки и возвращает результирующую строку. При этом символами пробелов считаются символы новой строки (\n), возврата каретки (\r), символы горизонтальной (\t) и вертикальной табуляции (\v), конца строки (\0) и обычные пробелы.
В зависимости от конкретной преследуемой цели вместо этой функции можно использовать функции ltrim() или chop(). Обе эти функции аналогичны функции trim() в том, что принимают интересующую строку в качестве параметра и возвращают отформатированную строку. Различие между ними состоит в том, что функция trim() удаляет пробелы в начале и конце строки, ltrim() удаляет пробелы только в начале строки (или левой ее части), a chop() — только в конце (или правой части) строки.
Функция nl2br() принимает строку в качестве параметра и заменяет в ней все символы новой строки дескриптором <BR> HTML. РНР поддерживает также функцию print(), выполняет ту же задачу, что и echo, но поскольку она является функцией, то возвращает значение (0 или 1, в зависимости от успешности выполнения).
Обе эти конструкции выводят строку "как есть". Используя функции printf() и sprintf(), можно применять несколько более сложное форматирование. В основном, эти функции работают практически одинаково, но printf() выводит сформатированную строку в окне браузера, a sprintf() возвращает сформатированную строку. Прототипы этих функций выглядят так:
string sprintf (string format [, mixed args ...])
int printf (string format [, mixed args ...])
В качестве первого параметра обеим этим функциям передается строка формата, описывающая основную форму вывода, в которой вместо переменных используются коды форматирования. Остальными параметрами являются переменные, которые будут подставляться в строку формата.
printf ("Total amount of order is %s.", $total);
Последовательность %s в строке формата называется спецификацией преобразования. Приведенная спецификация означает "заменить строкой". В данном случае она будет заменена значением переменной Stotal, интерпретируемым в качестве строки. Если бы значением, хранящимся в переменной Stotal, было 12.4, оба приведенные выражения привели к выводу 12.4. Преимущество использования функции printf() в том, что можно использовать более удобную спецификацию преобразования для указания того, что в действительности Stotal — число с плавающей точкой и оно должно содержать два знака после десятичной точки, как показано в следующем примере:
printf ("Total amount of order is %.2f", $total);
Строка формата может содержать несколько спецификаций преобразования. При использовании n спецификаций преобразования после строки формата необходимо указать n аргументов. Каждая спецификация преобразования будет замещена переформатированным аргументом в том порядке, в каком они перечислены. Например:
printf ("Total amount of order is %.2f (with shipping %.2f) ", $total, $total_shipping);
В данном случае первая спецификация преобразования будет использовать переменную Stotal, а вторая — переменную Stotal_shipping.
Все спецификации преобразования имеют одинаковый формат
%['дополняющий_сямвол][-][ширина][.точность]тип
Все спецификации преобразования начинаются с символа %. Если требуется вывести символ %, потребуется применить последовательность %%. Дополняющий_символ необязателен. Он будет использоваться для дополнения переменной до указанной ширины. Примером может служить добавление ведущих нулей к такому числу, как значение счетчика.
Символ "-" также является необязательным. Он указывает, что данные в поле будут выравниваться по левому краю, а не по правому, как определено по умолчанию. Параметр ширина указывает функции printf(), сколько места (в символах) необходимо для подстановки значения переменной. Параметр точность должен начинаться с десятичной точки. Он определяет количество отображаемых десятичных знаков после запятой.
Последним параметром спецификации является код типа. Краткое описание используемых кодов приведено в табл.
Определенные символы являются очень важной частью строки, но могут приводить к проблемам, в особенности при вставке в базу данных, поскольку она может интерпретировать их как управляющие символы. Такими символами являются кавычки (одинарные и двойные), символы обратной косой черты (\) и символ NUL. Чтобы отменить эти символы, перед ними необходимо поместить символ косой черты.
В РНР имеются две функции, которые специально предназначены для отмены символов. Прежде чем записать любые строки в базу данных, их нужно переформатировать с помощью функции AddSlashes(). Например:
$feedback = AddSlashes($feedback);
Подобно многим другим строковым функциям, AddSlashes() принимает строку в качестве параметра и возвращает переформатированную строку. При использовании функции AddSlashesQ строка будет сохранена в базе данных с
символами косой черты. При получении строки нужно не забыть удалить символы косой черты. Это можно сделать с помощью функции StripSlashes():
$feedback = StripSlashes($feedback);
Объединение и разделение строк с помощью строковых функций
array explode(string separator, string input);
Эта функция принимает строку input и разделяет ее на части по указанной разделительной строке separator. Части строки возвращаются в виде массива. Для получения имени домена из адреса электронной почты в сценарии можно ис-
пользовать следующий код:
$email_array = explode("@", $email);
преобразовав все буквы имени домена в прописные или строчные, а затем выполнив проверку:
$email_array[1] = strtoupper ($email_array[1]);
Эффекта, противоположного действию функции explodeQ, можно добиться, используя функции implode() или join(), которые идентичны. Например:
$new_email = implode("@", $email_array);
Эта функция принимает элементы из массива Semail_array и объединяет их со строкой, переданной в первом параметре. Вызов этой функции во много подобен вызову функции explode(), но ее действие противоположно.
функция strtok() получат фрагменты (называемые лексемами) из строки по одному. Эта функция — полезная альтернатива использованию функции explode() при обработке слов из строки по одному.
Прототип функции strtok() имеет следующий вид:
srting strtok(string input, string separator);
В качестве разделителя separator можно использовать символ или строку символов, но следует иметь в виду, что строка ввода будет разделяться по каждому из символов разделителя, а не по всей строке разделителя (как имеет место в функции explode).
Вызов функции strtok() не столь прост, как может показаться, судя по прототипу. Для получения первой лексемы из строки нужно вызвать функцию strtokQ со строкой, которую требуется разбить на лексемы, и разделителем. Для получения последующих лексем из строки достаточно передать функции единственный параметр - разделитель. Функция сохраняет собственный внутренний указатель на позицию в строке. Если требуется переустановить указатель, можно снова передать строку в функцию.
Как правило, функция srtok() используется следующим образом:
Stoken = strtok($feedback, " ");
echo $token."<br>" ;
while ($token!="")
{$token = strtok(" ");
echo $token."<br>";};
Функция substr() позволяет получить доступ к подстроке между заданными начальной и конечной позициями в строке. Для нашего примера она не подходит, но может оказаться полезной, если требуется разделить на части фиксированные отформатированные строки.
Функция substr() имеет следующий прототип:
string substr(string строка, int начало, int [длина] );
Эта функция возвращает подстроку из строки строка.
Эти функции могут использоваться для упорядочения строк, которое полезно при сортировке данных.
Прототип функции strcmp() имеет вид
int strcmp(string strl, string str2) ;
Функция принимает две строки, которые и будет сравнивать. Если они равны, функция вернет значение 0. Если в лексикографическом порядке строка strl следует за строкой str2 (или больше ее), функция strcmpQ вернет положительное число. Если строка strl меньше строки strl, функция strcmp() вернет отрицательное число. Эта функция является чувствительной к регистру.
Функция strcasecmpO идентична предыдущей за исключением того, что она не чувствительна к регистру.
Функция strnatcmpO и ее нечувствительный к регистру аналог srtnatcasecmpO появились в РНР 4. Эти функции сравнивают строки в соответствии с "естественным упорядочением", которое более привычно для человека. Например, strcmp() расположила бы строку "2" после строки "12", поскольку лексикографически она больше. Функция strnatcm() расположила бы эти строи в обратном порядке.
Длину строки можно проверить с помощью функции strlenQ. Если передать этой функции строку, она вернет ее длину. Например, strlen("hello") возвращает значение 5.
Для поиска строки внутри другой строки можно использовать любую из функций strstr(), strchr(), strrchr() или stristr().
Функция strstr() является наиболее общей и может использоваться для поиска соответствующей строки или символа внутри более длинной строки. Следует отметить, что в РНР функция strchr() полностью совпадает с функцией strstr(), хотя ее имя предполагает, что она применяется для поиска символа в строке, аналогично ее С-версии. В РНР любая из этих функций может использоваться для поиска строки внутри строки, в том числе для поиска строки, состоящей только из одного символа.
Функция strstr() имеет следующий прототип:
string strstr(string haystack, string needle);
В качестве параметра функции передается строка haystack, в которой нужно выполнить поиск, и строка needle, которую требуется найти. В случае обнаружения полного соответствия со строкой needle функция возвращает часть строки haystack, начинающуюся со строки needle; в противном случае она возвращает значение false. Если строка needle встречается более одного раза, возвращаемая строка будет начинаться с первого вхождения сроки needle.
Существует два варианта функции strstr(). Первый — функция stristrQ, которая практически идентична предыдущей, но не чувствительна к регистру. Это удобно в данном приложении, поскольку клиент мог бы ввести "delivery", "Delivery" или "DELIVER".
Второй вариант — функция strrchr(), которая также почти идентична функции strstr(), но будет возвращать часть строки haystack, начиная с последнего вхождения строки needle, вместо подстроки они возвращают числовую позицию строки needle внутри строки haystack.
Функция strposO имеет следующий прототип:
string strpos(string haystack, string needle, int [offset] );
Целочисленное возвращаемое значение представляет первое вхождение строки needle внутри строки haystack. Как обычно, первый символ размещается в нулевой позиции. Необязательный параметр offset используется для указания позиции внутри строки haystack, с которой должен начинаться поиск Функция strrpos() действует почти так же, но будет возвращать позицию последнего вхождения строки needle в строке haystack. В отличие от функции strposQ, эта функция работает только с одно-символьной строкой needle. Поэтому, если передать строку как needle, для сопоставления функция будет использоваться только первый символ строки.
В любом из этих случаев, если needle не является строкой, функция strpos() или strrposQ будет возвращать значение false. Это может порождать проблемы, поскольку в слабо типизированном языке наподобие РНР значение false эквивалентно 0, т.е., первому символу в строке.
Во избежание этой проблемы можно использовать операцию === для проверки возвращаемых значений:
$result = strpos($test, "H");
if ($result === false)
echo "Not found"
else
echo "Found at position 0";
Строковая функция, которую чаще всего используют для замены — str_replace(). Она имеет следующий прототип:
string str_replace(string needle, string new_needle, string haystack);
Эта функция будет замещать все экземпляры строки needle в строке haystack на строку new_needle. Функция substr_replace() используется для поиска и замены конкретной подстроки в строке. Она имеет следующий прототип:
string substr_replace(string needle, string replacement, int start, int [length] ) ;
Эта функция будет замещать часть строки string строкой replacement. Какую именно часть — зависит от значений параметра start и необязательного параметра length. Значение start представляет смещение позиции в строке, с которого должна начинаться замена. Если оно равно 0 или положительно, то определяет смещение от начала строки, если отрицательно — смещение от конца строки. Например, следующая строка кода будет заменять последний символ в переменной $test символом "X":
$test = substr_replace($test, "X", -1) ;
Параметр length необязателен и представляет позицию, в которой замена должна быть прекращена. Если это значение не указано, замена будет выполняться от позиции, определенной параметром start, и до конца строки.
Если значение length равно нулю, фактически строка замены будет вставляться в строку без замещения существующей строки. Положительное значение параметра length представляет количество символов, которые требуется заменить новой строкой. Отрицательное значение параметра length представляет позицию, в которой нужно прекратить замену символов, определяемую от конца строки.
долговременное содержание сайтов осуществляется проще, когда реализовано разграничение логики и содержимого. Это сводится к разделению PHP-кода и HTML-кода.
три основных подхода к разделению логики и содержимого:
• Для хранения различных частей содержимого используйте подключаемые файлы. Это упрощенный подход, но вполне эффективный, если сайт в основном статичный.
• Воспользуйтесь API-интерфейсом функций либо классов с набором собственных функций для подключения динамического содержимого к статическим шаблонам страницы.
• Воспользуйтесь системой шаблонов. Она анализирует статические шаблоны и применяет регулярные выражения для замены дескрипторов-заполнителей динамическими данными. Главное преимущество данного решения состоит в том, что проектировать шаблоны может кто-то другой, кому совершенно не требуется вникать в PHP-код. Необходимо иметь возможность использования предоставляемых шаблонов с минимальными изменениями. Существует целый ряд систем шаблонов. Возможно, наиболее популярной из них является FastTemplate: http://thewebmasters.net
home.html:
<html><head><title>TIA Consulting Pty Ltd</title>
<style>h1 (color: white; font-size :24pt; text-align : center ;font-family : arial , sans-serif)
.menu {color: white; font-size: 12pt; text-align : center ;font-family : arial , sans-serif; font-weight : bold)
td {background: black)
p {color :black; font-size: 12pt; text-align: justify;font-family: arial , sans-serif)
p. foot {color: white; font-size :9pt; text-align: center;font-family : arial , sans-serif ; font-weight : bold)
a : link , a : visited, a : active {color : white )
</style>
</head>
<body>
<! — page header — >
<table width="100%" cellpadding = 12 cellspacing =0 border = 0>
<tr bgcolor = black><td align = leftximg src = "logo.gif "X/td><td>
<hl>TLA Consulting</hl>
</td><td align = rightximg ere = "logo.gif "X/td></tr>
</table>
<! — menu -->
<table width = "100%" bgcolor = white cellpadding = 4 cellspacing = 4>
<tr ><td width = "25%">
<img src = "s-logo.gif "> <span class=menu>Home</spanx/td>
<td width = "25%">
<img src = "s-logo.gif "> <span class=menu>Contact</spanX/td>
<td width = "25%">
<img src = "s-logo.gif "> <span class=menu>Services</spanx/td>
<td width = "25%">
<img src = "s-logo.gif "> <span class=menu>Site Map</spanX/td>
</tr>
</table>
<!-- page content — >
<p>Welcome to the home of TLA Consulting. Please take some time to get to know us . </p>
<p>We specialize in serving your business needs and hope to hear from you soon.</p>
<!-- page footer — >
<table width = "100%" bgcolor = black cellpadding = 12 border = 0>
<tr><td>
<p class=foot>ficopy; TLA Consulting Pty Ltd.</p>
<p class=foot>Please see our <a href ="">legal information page</a></p>
</td></tr>
</table>
</body></html>
Вполне можно разделить этот файл и назвать части header.inc, home.php и footer.inc. Файлы header.inc и footer.inc содержат код, который будет повторно использоваться на других страницах. Файл home.php служит заменой для файла home.html и содержит уникальное содержимое страницы и два оператора require()
home.php:
<? require ("header .inc") ; ?>
<!-- page content --! >
<p>Welcome to the home of TLA Consulting. Please take some time to get to know us.</p>
<p>We specialize in serving your business needs and hope to hear from you soon.</p>
<? require ("footer . inc") ; ?>
Операторы require() в файле home.php загружают файлы header.inc и footer.inc. Имена, присвоенные этим файлам, не влияют на способ их обработки при вызове через оператор require(). Общепринято, но не обязательно, называть частичные файлы, которые предназначены для включения в другие файлы, наподобие something.mc (в данном случае inc означает include (включить)).
При использовании оператора require() для загрузки файла, файл фактически становится частью PHP-файла и будет выполняться как таковой. любые хранящиеся внутри него PHP-операторы будут обработаны.
Кроме того, общепринято и имеет смысл помещать включаемые файлы в каталог, который доступен сценарию, но не позволяет включаемым файлам быть загруженными самостоятельно через Web-сервер. Это предотвратит самостоятельную загрузку этих файлов, что может
а) вызывать какие-либо ошибки, если расширением файла является .php, но он содержит только часть страницы или сценария, или
Ь) при использовании другого расширения разрешать пользователям читать исходный код.
header.inc:
<html><head><title>TLA Consulting Pty Ltd</title>
<style>hi {color:white; font-size:24pt; text-align:center;font-family:arial,sans-serif}
.menu {color:white; font-size:12pt; text-align:center;font-family:arial,sans-serif; font-weight:bold}
td {background:black}
p {color:black; font-size:12pt; text-align:justify;font-family:arial,sans-serif)
p.foot {color:white; font-size:9pt; text-align:center;font-family:arial,sans-serif; font-weight:bold)
a:link,a:visited,a:active {color:white}
</style>
</head>
<body>
<!-- page header —>
<table width="100%" cellpadding = 12 cellspacing =0 border = 0>
<tr bgcolor = black><td align = leftximg src = "logo.gif "></td><td>
<hl>TLA Consulting</hl>
</td><td align = rightximg src = "logo. gif "X/td></tr>
</table>
<!— menu -->
<table width = "100%" bgcolor = white cellpadding = 4 cellspacing= 4>
<tr ><td width = "25%">
<img src = "s-logo.gif"> <span class=menu>Home</spanX/td>
<td width = "25%">
<img src = "s-logo.gif"> <span class=menu>Contact</span></td>
<td width = "25%">
<img src = "s-logo.gif"> <span class=menu>Services</spanX/td>
<td width = "25%">
<img src = "s-logo.gif"> <span class=menu>Site Map</spanX/td>
</tr>
</table>
footer.inc:
<!— page footer —>
<table width = "100%" bgcolor = black cellpadding = 12 border = 0>
<tr><td>
<p class=foot>© TLA Consulting Pty Ltd.</p>
<p class=foot>Please see our
<a href =" legal .php3">legal information page</aX/p>
</td></tr>
</table>
</body>
</html>
В приведенном примере в теле, верхнем и нижнем колонтитулах страниц используется простой HTML-код. Это вовсе не обязательно. Внутри этих файлов можно было бы использовать PHP-операторы для динамической генерации частей страницы.
Основные шаги выполнения запросов
к базе данных через Web
В любом сценарии, который обеспечивает доступ к базе данных из Web, имеется несколько базовых шагов:
1. Проверка и фильтрация данных, исходящих от пользователя.
2. Установка соединения с требуемой базой данных.
3. Передача запроса в базу данных.
4. Получение результатов.
5. Представление результатов пользователю.
search.html:
<html><head><title>Book-O-Rama Catalog Search</title></head>
<body>
<hl>Book-0-Rama Catalog Search</hl>
<form action="results.php" method="post">
Choose Search Type:<br>
<select name="searchtype">
<option value="author">Author
<option value="title">Title
<option value="isbn">ISBN
</select>
<br>Enter Search Term:<br>
<input name="searchterm" type=text><br><input type=submit value="Search">
</form>
</body></html>
После того как пользователь нажмет на кнопке Search, вызывается сценарий results.php:
<html><head><title>Book-O-Rama Search Results</title></head>
<body>
<hl>Book-O-Rama Search Results</hl>
<? trim($searchterm);
if (!$searchtype || !$searchterm){
echo "You have not entered search details. Please go back and try again. " ;
exit;}
$searchtype = addslashes ($searchtype) ;
$searchterm = addslashes ($searchterm) ;
@ $db = mysql_pconnect("localhost" , "bookorama", "bookorama");
if (!$db){
echo "Error: Could not connect to database. Please try again later.";
exit;}
mysql_select_db( "books") ;
$query = "select * from books where " . $searchtype. " like ‘%" . $ search term. "% ' " ;
$result = mysql_query($query) ;
$num_results = mysql_num_rows ($result) ;
echo "<p>Number of books found: ".$num_results."</p>";
for ($i=0; $i <$num_results; $i++){
$row = mysql_fetch_array($result);
echo "<p><strong>". ($i+l) ." . Title: " ;
echo htmlspecialchars( stripslashes($row["title"]));
echo "</strongXbr>Author: ";
echo htmlspecialchars (stripslashes($row["author"]));
echo "<br>ISBN: ";
echo htmlspecialchars (stripslashes($row["isbn" ] )) ;
echo "<br>Price: " ;
echo htmlspecialchars (stripslashes($row["price"] ));
echo "</p>";}
?>
</body></html>
1. Сначала необходимо убрать все лишние пробелы по краям слова, которые мог случайно набрать пользователь. Справиться с этим поможет функция trim(), применяемая к Ssearchterm (критерий поиска): trim($searchterm);
Далее нужно убедиться, что пользователь указал критерий и тип поиска. Заметьте, это проверяется лишь тогда, когда критерий поиска не содержит лишние пробелы. Если поменять эти этапы местами, может возникнуть ситуация, когда критерий вроде и введен, сообщения об ошибке быть не должно, однако критерий содержит только пробелы, которые полностью удаляются функцией trim():
if (!$searchtype | | !$searchterm){echo "You have not entered search details. Please go back and try again. " ;exit;}
В этом случае выдается сообщение о том, что критерий поиска не введен. Мы проверили переменную Ssearchtype даже в том случае, когда она поступает из оператора SELECT. Вас может заинтересовать, зачем проверять входные данные. Не забывайте, что база данных может иметь не один интерфейс. Например, Amazon располагает большим количеством филиалов, которые используют свои поисковые интерфейсы. Вследствие того, что пользователи могут заходить с разных рабочих станций, возникает и потенциальная угроза безопасности. В случае задействования данных, которые вводят другие пользователи, необходимо тщательно фильтровать вводимые данные от управляющих символов(addslashes() и stripslashes()).
В нашем случае к критерию поиска применяется функция addslashes(): $searchterm = addslashes ($searchterm);
К данным, исходящим из базы, применяется stripslashes(). Введенные данные не содержат косых линий, равно как и управляющих символов. То есть вызов stripslashes() не поможет. При построении Web-интерфейса для базы данных велики шансы того, что потребуется вносить данные о новых книгах, а детали, внесенные пользователем, могут содержать специальные символы. Сохраняя их в базе данных, мы обращаемся к addslashes(), а это означает, что при извлечении данных необходимо будет вызывать stripslashes(). Обратите внимание, что это хорошая привычка.
Функцию htmlspecialchars() применяют для кодировки символов, которые в HTML имеют особое значение. В наших тестовых данных нет амперсандов (&), знаков "меньше" (<), "больше" (>), двойных кавычек ("), однако в названиях многих замечательных книг может повстречаться амперсанд. Использование этой функции застраховывает от грядущих ошибок.
2. Установка соединения
Для подключения к серверу MySQL в сценарии присутствует такая строка:
@ $db = mysql_pconnect("localhost", "bookorama", "bookorama");
Для подключения к базе данных используется функция mysql_pconnect() со следующим прототипом:
int mysql_pconnect ( [string host [.-port] [:/socketpath] ] ,[string user] , [string password] ) ;
Потребуется указать имя узла (host), на котором размещен сервер MySQL, имя пользователя (user), чтобы войти в него, и пароль (password). Все это в принципе необязательно и если не указать все вышеперечисленное, функция воспользуется значениями по умолчанию — локальная машина вместо узла, имя пользователя, под которым запущен РНР, и пустой пароль. В случае успеха функция вернет идентификатор связи с базой данных (который следует сохранить для дальнейшего использования), а в случае неудачи — значение false. Результат не стоит игнорировать, поскольку без соединения с базой данных работа невозможна. Это делает Следующий код:
if (!$db){echo "Error: Could not connect to database. Please try again later."; exit;}
Как альтернативу, можно использовать другую функцию, которая делает практически то же самое — mysql_connect(). Единственное отличие состоит в том, что mysql_connect() устанавливает постоянное соединение с базой данных. Обычное соединение с базой данных закрывается, когда сценарий завершает свое выполнение или когда обращается к функции mysql_close(). Постоянное соединение остается открытым и после того, как сценарий выполнен, а функцией mysql_close() его закрыть нельзя.
Может возникнуть вопрос, для чего это нужно. Ответ таков: соединение с базой данных предполагает некоторые непроизводительные затраты, что требует времени. Когда вызывается mysql_pconnect(), прежде чем она попытается подключиться к базе данных, она автоматически проверит, нет ли уже открытого постоянного соединения. Если есть, она не станет открывать новое. Это и время экономит, и предотвращает перегрузку сервера. Однако если РНР выполняется как CGI, то постоянное соединение окажется не таким уж и постоянным. (Каждый вызов сценария РНР запускает новую копию механизма РНР и закрывает ее, когда сценарий завершает свою работу. Это, в свою очередь, также закрывает любое постоянное соединение.)
Помните, что количество соединений в MySQL, которые существуют одновременно, ограничено. Границу устанавливает параметр max_connections. Его задача (как и родственного ему параметра Apache MaxClients) — заставить сервер отвергать новые запросы на соединение, когда ресурсы узла заняты или когда программное обеспечение не функционирует. Значения этих параметров можно изменять, редактируя файл конфигурации. Чтобы настроить MaxClients в Apache, следует править файл httpd.conf. Настройка max_connections в MySQL осуществляется за счет редактирования файла my.conf. Если вы пользуетесь постоянными соединениями, и практически каждой странице на вашем сайте требуется доступ к базе данных, вам, пожалуй, понадобится постоянное соединение для каждого процесса Apache. Если же используются значения параметров, принятые по умолчанию, могут возникнуть определенные сложности. По умолчанию Apache допускает до 150 соединений, a MySQL — только 100. В особо напряженное время соединений может не хватить. Поэтому лучше всего настроить параметры так, чтобы у каждого процесса Web-сервера было свое соединение, конечно, с оглядкой на технические возможности применяемых аппаратных средств.
3. Выбор базы данных
Работая с MySQL из командной строки, необходимо указывать, какая база данных нужна: use books ;
То же самое необходимо и при подключении из Web. Это может сделать РНР-функция mysql_select_db(): Прототип этой функции выглядит так:
int mysql_select_db (string database, [int database_connection] ) ;
В результате будет использоваться база данных с именем database. Можно также использовать соединение с базой данных, для которого требуется выполнить эту операцию (в нашем случае $db), однако, если его не указать, будет использоваться последнее открытое соединение. Если открытое соединение не существует, оно открывается по умолчанию, как если бы вызывалась mysql_connect().
4. Выполнение запроса к базе данных
Чтобы осуществить запрос, можно воспользоваться функцией mysql_query(). Однако прежде запрос необходимо настроить: $query = "select * from books where ".$searchtype." like'%".$searchterm."%' ";
В этом случае будет отыскиваться значение, введенное пользователем (Ssearchterm), в поле, которое указал пользователь (Ssearchtype). Вы, наверное, обратили внимание на то, что мы употребили like, отдав ему предпочтение перед equal — толерантность никогда не бывает излишней.
ПОДСКАЗКА: Не забывайте, что запрос, отправляемый вами в MySQL, не требует в конце точки с запятой, в отличие от запроса, который вводится в среде монитора MySQL.
Теперь можно выполнить запрос: $result = mysql_query ($query) ;
Прототип функции mysql_query() таков:
int mysql_query(string query, [int dataiase_connection] );
В функцию передается запрос, который должен быть выполнен; можно также передать еще и соединение с базой данных (в нашем случае $db). Если его не указать, будет использоваться последнее открытое соединение. Если такового нет, функция откроет соединение точно так же, как при выполнении mysql_connect().
Возможно, вместо этого захочется воспользоваться функцией mysql_db_query().
Рассмотрим ее прототип:
int mysql_db_query(string database, string query,[int database_connection] ) ;
Почти то же самое, только здесь можно указать базу данных, в которой требуется производить поиск. В каком-то смысле это комбинация функций mysql_select_db() и mysql_query().
Обе функции возвращают идентификатор результата (что позволяет получить результаты поиска) в случае успеха и значение false в случае неудачи. Идентификатор результата следует сохранить (так же, как в нашем случае с $result), чтобы извлечь из него некоторую пользу.
5. Получение результатов запроса
Разнообразие функций дает возможность получить результат различными способами. Идентификатор результата — это ключ доступа к строкам, возвращенным запросом, которых может быть нуль, одна и более. В нашем примере использовались две функции: mysql_numrows() и mysql_fetch_array().
Функция mysql_numrows() сообщает количество строк, которые возвращает запрос. В нее следует передать идентификатор результата: $num_results = mysql_num_rows($result) ;
Это полезно знать, если планируется обрабатывать или отображать результаты. Зная их количество, можно организовать цикл: for ($i=0; $i <nuin_results; $i++){// обработка результатов}
На каждой итерации цикла происходит вызов mysql_fetch_array(). Цикл не будет выполняться, если нет строк. Эта функция берет каждую строку из списка результата и возвращает ее в виде ассоциативного массива, с ключом как именем атрибута и значением как соответствующим значением массива: $row = mysql_fetch_array($result) ;
Имея $row в ассоциативном массиве, можно пройти каждое поле и должным образом его отобразить:
echo "<br>ISBN: "; echo stripslashes($row["isbn"] ) ;
Как уже упоминалось, stripslashesQ вызывают для того, чтобы "подчистить" значение, прежде чем отображать его пользователю. Существуют несколько вариантов получения результата из идентификатора результата. Вместо ассоциативного массива можно воспользоваться нумерованным массивом, применив mysql_fetch_row():
$row = mysql_fetch_row($result);
Значения атрибутов будут храниться в каждом порядковом значении $row[0], $row[l] и т.д.
С помощью функции mysql_fetch_object() можно выбрать строку внутрь объекта: $row = mysql_fetch_object($result);
После этого к каждому атрибуту можно получить доступ через $row->title, $row->author и т.д.
Каждый из этих вариантов подразумевает выборку строки за раз. Другой вариант — получить доступ, используя mysql_result(). Для этого потребуется указать номер строки (от 0 до количества строк минус 1) и название поля, например: $row = mysql_result($result, $i, "title");
Название поля можно задать в виде строки (либо в форме "title" либо в форме "books.title") или номером (как в mysql_fetch_row()). He стоит смешивать mysql_result() с другими функциями выборки.
Строчно-ориентированные функции выборки намного более эффективны, нежели mysql_result(), так что лучше использовать одну из них.
6. Отсоединение от базы данных
Для закрытия непостоянного соединения применяется функция:
mysql_close( database_connection) ;
Однако в этом нет особой необходимости, поскольку с завершением выполнения сценария соединение закроется автоматически.
7. Внесение новой информации в базу данных
Внесение новой информации очень похоже на получение существующей. Нужно пройти те же шаги — установить соединение, отправить запрос и проверить результаты. Только в данном случае вместо SELECT будет использоваться INSERT. Хоть все вроде и просто, но на пример взглянуть никогда не помешает.
insert_book.php:
<html><head><title>Book-O-Rama Book Entry Results</title></head>
<body>
<hl>Book-O-Rama Book Entry Results</hl>
<?
if (!$isbn || !$author || !$title I I ! $price){
echo "You have not entered all the required details.<br> Please go back and try again.";
exit;}
$isbn = addslashes($isbn);
$author = addslashes($author);
$title = addslashes($title) ;
$price = doubleval($price);
@ $db = mysql_pconnect("localhost", "bookorama", "bookorama");
if (!$db){
echo "Error: Could not connect to database. Please try again later . " ;
exit;}
mysql_select_db( "books") ;
$query = "insert into books values( '" .$isbn." ' , ' " .$author.$result = mysql_query ($query) ;
if ($result)
echo mysql_af f ected_rows ( ) . " book inserted into database.";' " .$title. " ' , ' " .$price. " ' )
?>
</body>
</html>
Одно существенное различие между INSERT и SELECT заключается в использовании mysql_affected_rows():
echo mysql_affected_rows(). " book inserted into database.";
В предыдущем сценарии функция mysql_num_rows() применялась для определения количества строк, которые будет возвращать SELECT. При написании запросов, которые изменяют базу данных, например, INSERT, DELETE, UPDATE, следует использовать mysql_affected_rows().
Дополнительные функции
Если во время выполнения сценария возникают проблемы, связанные с нехваткой памяти, может пригодиться функция mysql_free_result(). Вот ее прототип:
int mysql_free_result(int result);
Она вызывается с идентификатором результата: mysql_free_result($result);
В итоге освобождается память, занимаемая результатом. Очевидно, что до обработки результата эта функция вызываться не должна.
Для создания новой базы данных MySQL из PHP-сценария применяется функция mysql_create_db(), а для удаления базы данных — mysql_drop_db().
Рассмотрим прототипы этих функций:
int mysql_create_db(string database, [int database_connection] );
int mysql_drop_db(string database, [int database_connection] ) ;
Обе функции используют имя базы данных и соединение. Если соединения нет, будет использоваться последнее открытое. Функции создают либо удаляют указанную базу данных. В случае успеха функции возвращают значение true, а в случае неудачи — false.
РНР поддерживает различные библиотеки, что дает возможность подключаться к огромному количеству баз данных, включая Oracle, Microsoft SQL Server, mSQL и PostgreSQL. В целом принципы подключения и подачи запросов любой из этих баз данных одни и те же. Названия функций могут быть разными, разные базы данных могут иметь разную функциональность Если необходимо использовать базу данных, которая не имеет специфической библиотеки, доступной в РНР, можно прибегнуть к обобщенным функциям ODBC.
ODBC — это открытый интерфейс доступа к базам данных и является стандартом подключения к базам данных. Функциональность ODBC нельзя назвать чересчур широкой, однако на то имеются вполне очевидные причины: либо универсальная совместимость, либо задействование специфических возможностей каждой системы.
РНР поддерживает два стиля синтаксиса регулярных выражений: POSIX и Perl.
Стиль POSIX регулярных выражений компилируется в РНР по умолчанию, а стиль Perl
можно активизировать, выполнив компиляцию с библиотекой PCRE (Perl-compatible
regular expression — Perl-совместимые регулярные выражения)
Мы рассмотрим более простой стиль POSIX
Наборы символов и классы
Прежде всего, символ "." можно использовать в качестве группового символа для любого другого одиночного символа, за исключением символа новой строки (\п). Например, регулярное выражение
.at
соответствует, в частности, строкам "cat", "sat" и "mat", но оно соответствует также и строке "#at"
Если соответствие необходимо ограничить символами от а до г, его можно указать следующим образом:
[a-z]
Все, заключенное в специальные символы квадратных скобок [ и ], представляет класс символов — набор символов, к которому должен принадлежать сопоставляемый символ. Обратите внимание, что заключенное в квадратные скобки выражение сопоставляется только с одиночным символом.Набор можно указать в виде списка. Например, [aeiou] означает любую гласную английского алфавита.
Можно описать также диапазон, как это было только что сделано с помощью символа дефиса, или набор диапазонов: [a-zA-Z] Этот набор диапазонов означает любой строчный или прописной символ английского алфавита. Наборы можно использовать также для указания символа, который не может быть членом набора. Например, [^a-z] соответствует любому символу, не относящемуся к диапазону a-z. Когда он помещен внутрь квадратных скобок, символ вставки ^ означает "не". При использовании вне квадратных скобок он имеет другое значение, что будет вскоре рассмотрено.
Повторение
Часто требуется указать возможность наличия нескольких вхождений конкретной строки или класса символов. В регулярном выражении это можно сделать с помощью двух специальных символов. Символ * означает, что шаблон может повторяться нуль или более раз, а символ + 1 или более раз. Эти символы должны указываться непосредственно после той части выражения, к которой они применяются. Например,
[[:alnum:]]+
означает "по крайней мере один алфавитно-цифровой символ".
Подвыражения
Часто удобно разделять выражение на подвыражения, чтобы, например, можно было представить выражение "по меньшей мере одна из этих строк, за которой следует именно одна из следующих". Это можно сделать с использованием круглых скобок совершено так же, как это делается в арифметических выражениях. Например,
(very )*large
соответствует строкам "large", "very large", "very very large" и т.д.
Подсчитываемые подвыражения
Количество повторений какой-либо строки можно указать с помощью числового выражения, заключенного в фигурные скобки ({}). При этом можно указывать точное число повторений ({3} означает в точности 3 повторения), диапазон повторений ({2, 4} означает от 2 до 4 повторений) или открытый диапазон повторений ({2,} означает не менее двух повторений).Например,
(very ){1, 3}
соответствует строкам "very", "very very" и "very very very".
Привязка к началу или концу строки
Можно указать, должно ли конкретное подвыражение появляться в начале, конце или в начале и конце строки. Это достаточно удобно, когда необходимо убедиться, что в строке присутствует только искомый термин и ничего больше. Символ вставки (^) используется в начале регулярного выражения для указания того, что оно должно присутствовать в начале просматриваемой строки, а символ $ используется в конце регулярного выражения для указания того, что оно должно присутствовать в конце строки. Например, следующая строка соответствует наличию подстроки bob в начале строки:
^bob
Эта строка соответствует наличию подстроки com в конце строки:
com $
И, наконец, это выражение соответствует любому одиночному символ от а до z, расположенному в отдельной строке: ^ [а-z]$
Ветвление
Вариант в регулярном выражении можно представить с помощью символа вертикальной черты (|). Например, если требуется сопоставить строку com, edu или net, можно воспользоваться выражением:
(com) | (edu) | (net)
Сопоставление с литеральными значениями специальных символов
Если нужно сопоставить Один из специальных символов, упомянутых в этом разделе, таких как ., { или $, перед ним необходимо поместить символ косой черты (\). Если нужно представить символ косой черты, его следует заменить двумя символами косой черты, т.е. \\.
Краткое описание
специальных символов
Пример:
Проверка правильности адреса электронной почты клиента путем кодирования стандартизованного формата адреса электронной почты в регулярном выражении. Формат включает некоторые алфавитно-цифровые символы и символы пунктуации, за которыми следуют символ @, затем строка алфавитно-цифровых символов или дефисов, затем точка, затем опять алфавитно-цифровые символы и дефисы и, возможно, дополнительные точки, вплоть до конца строки; этот формат можно закодировать следующим образом:
^ [a-zA-ZO-9_]+@[a-zA-ZO-9\-]+\.[a-zA-ZO-9\-\.]+$
Подвыражение ^ [a-zA-ZO-9_]+ означает "начало строки по меньшей мере с одной буквы, цифры или символа подчеркивания, или какого-либо их сочетания". Символ @ соответствует литеральному значению @. Подвыражение [a-zA-ZO-9\-]+ соответствует первой части имени хоста, включающего алфавитно-цифровые символы и дефисы. Обратите внимание, что перед символом дефиса поставлена косая черта, поскольку внутри квадратных скобок он является специальным символом. Комбинация \. соответствует литеральному значению ".".
Подвыражение [a-zA-ZO-9\-\.]+$ соответствует остальной части имени домена, включающего буквы, цифры, дефисы и дополнительные точки, если они требуются, вплоть до конца строки.
Небольшой анализ показывает, что можно ввести неправильные адреса электронной почты, которые все же будут соответствовать этому регулярному выражению. Практически невозможно предусмотреть все возможные варианты адресов, но это регулярное выражение позволит все-таки немного улучшить ситуацию
Поиск подстрок с помощью регулярных выражений
Поиск подстрок — основное применение только что рассмотренных регулярных выражений. В РНР существуют две функции, предназначенные для сопоставления с регулярными выражениями: ereg() и eregi().
Функция ereg() имеет следующий прототип:
int ereg(string pattern, string search, array [matches]);
Эта функция выполняет поиск в строке search, отыскивая в ней соответствия с регулярным выражением, определенным в шаблоне pattern. Если соответствия подвыражений с шаблоном pattern будут найдены, они сохраняются в массиве соответствий matches, по одному подвыражению в каждом элементе массива.
Функция eregi() идентична предыдущей, за исключением того, что она не чувствительна к регистру.
if (!eregi("^ [a-zA-Z0-9_]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-\.]+$", $email) ){
echo "That is not a valid email address. Please return to the previous page and try again." ;
exit;}
$toaddress = "feedback@bobsdomain.com"; // значение по умолчанию
if (eregi("shop|customer service|retail", $feedback))
$toaddress = "retail@bobsdomain.com";
else if (eregi("deliver.*|fulfil.*", $feedback))
$toaddress = "fulfilment@bobsdomain.com";
else if (eregi("bill|account", $feedback))
$toaddress = "accounts@bobsdomain.com";
if (eregi("bigcustomer\.com", $email))
$toaddress = "bob@bobsdomain.com";
Замена с помощью регулярных выражений
Регулярные выражения можно использовать также для поиска и замены подстрок так же, как это делалось с помощью функции str_replace(). Для выполнения этой задачи существуют две функции: ereg_replace() и eregi_replace(). Функция ereg_replace() имеет следующий прототип:
string ereg_replace(string pattern, string replacement, string search);
Эта функция ищет регулярное выражение pattern в строке search и заменяет его строкой replacement.
Функция eregi_replace() идентична предыдущей, но не чувствительна к регистру.
Разделение строк с помощью регулярных выражений
Еще одна полезная функция обработки регулярных выражений — split(), которая имеет следующий прототип:
array split(string pattern, string search, int [max]);
Эта функция разделяет строку search на подстроки по регулярному выражению pattern и возвращает подстроки в массив. Целочисленный параметр max ограничивает количество элементов, которые могут быть помещены в массив.
Эта функция может оказаться полезной для разделения имен доменов или дат. Например,
$domain = "yallara.cs.rmit.edu.au";
$arr = split ( " \. " , $domain);
while (list($key, $value) = each ($arr))
echo "<br>".$value;
Этот фрагмент кода разделяет имя хоста на пять компонентов и выводит каждый из них в отдельной строке.