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

web - tec / PHP 5 для начинающи

.pdf
Скачиваний:
69
Добавлен:
12.06.2015
Размер:
26.79 Mб
Скачать

Логические операторы, циклы и массивы 213

Затем создается выпадающий список, содержащий пять пунктов, соответствующих пяти оценкам от A до F. Для хранения оценок создается массив $math, который PHP сможет передать следующему сценарию:

echo"<td><select name='math[]'> <option>A</option> <option>B</option> <option>C</option> <option>D</option> <option>F</option>

</select>";

Значение для второй части сценария передается через скрытое поле формы, кото+ рое имеет то же имя, что и массив с именами студентов. Чтобы указать, что данный эле+ мент управления должен быть массивом, к его имени добавляются квадратные скобки. Для каждого студента передается имя элемента управления, а затем цикл завершается:

echo"<input type='hidden' name='student[]' value='$name'></td>";

}

После цикла вставляется кнопка отправки запроса и форма закрывается:

?>

</tr>

<tr><td> </td><td>

<input type="submit" value="Показать оценки"> </td></tr>

</form>

</table>

Вторая часть программы получает данные из формы. Эта часть состоит из цикла, сортировки и еще одного цикла.

Первый цикл используется для связи двух массивов, полученных из формы. Это делается путем конкатенации оценки и имени студента и сохранения результата в но+ вом массиве $gradestudent:

<hr>

<table border="1">

<tr><td colspan="2">

Оценки по математике расположены в следующем порядке: </td></tr>

<?php

while (list($index,$value)=each($_POST['math']))

{

$gradestudent[]=$_POST['math'][$index].$_POST['student'][$index];

}

Из кода первой части сценария известно, что значение элемента с определенным индексом в массиве $math связано со значением элемента с таким же индексом в мас+ сиве $student. Поэтому конкатенация представляет собой верный способ объедине+ ния связанных значений из каждого массива. Результирующий массив $gradestudent содержит следующие данные:

CАльберт Эйнштейн FИван Грозный BНаполеон DСаймон Боливар AИсаак Ньютон

Теперь необходимо соответствующим образом отсортировать массив $gradestudent:

asort($gradestudent);

214 Глава 4

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

while (list($index,$value)=each($gradestudent))

{

echo "<tr><td><b>$_POST['student'][$index]</b></td><td>$_POST[math][$index]</td> </tr>";

}

}

?>

</table>

Чтобы понять, как это работает, следует вспомнить, что массив $gradestudent отсортирован по оценкам. Во время сортировки порядок элементов изменился, ин+ дексы связаны со значениями так же, как и до сортировки. Каждый элемент массива $gradestudent представляет собой конкатенацию соответствующих элементов мас+ сивов $math и $student. Что же произойдет, если отображать элементы из массивов $_POST[‘math’] и $_POST[‘student’] в том порядке, в каком их индексы распо+ ложены в массиве $gradestudent? Поскольку индексы всех этих массивов согласо+ ваны, элементы массивов $math и $student выводятся отсортированными также по оценкам, как показано в следующей таблице:

$index

$student

$math

Отсортированный массив $gradestudent

 

 

 

 

4

Исаак Ньютон

A

“AИсаак Ньютон”

2

Наполеон

B

“BНаполеон”

0

Альберт Эйнштейн

C

“CАльберт Эйнштейн”

3

Саймон Боливар

D

“DСаймон Боливар”

1

Иван Грозный

F

“FИван Грозный”

Известно, что использование функций list() и each() позволяет получить значе+ ния из отсортированного массива $gradestudent в том порядке, в котором они распо+ ложены в массиве, поэтому код выводит элементы из массивов $_POST['math'] и $_POST['student'] также отсортированными по оценкам.

Функция array_multisort()

Функция array_multisort() сортирует несколько массивов или многомерные массивы. В качестве аргументов она принимает имена массивов. При работе с несколь+ кими массивами функция сортирует первый массив и фиксирует индексы всех повто+ ряющихся элементов данного массива. Затем она сортирует повторяющиеся элементы согласно соответствующим индексам во втором массиве. Наконец, функция сортирует второй массив в том же порядке, что и первый. Рассмотрим предыдущий пример. Мож+ но изменить код в сценарии exam.php и использовать функцию array_multisort():

<?php array_multisort($math,$student);

while (list($index,$value)=each($student))

{

echo "<br>$student[$index] - $math[$index]";

}

?>

Логические операторы, циклы и массивы 215

Теперь представим, что произойдет, если данная функция отсортирует следующие оценки (в массиве $math) для данных студентов (имена которых хранятся в массиве $student):

Альберт Эйнштейн A Иван Грозный F Наполеон D

Саймон Боливар D

Исаак Ньютон A

Сначала функция array_multisort() сортирует массив $math[], в результате чего оценки располагаются так: A, A, D, D, F. Поскольку для каждой из оценок A и D имеется две записи, функция запоминает индексы двух A+записей (0 и 4), обращается ко второму массиву $student[] и сортирует элементы 0 (Альберт Эйнштейн) и 4 (Исаак Ньютон) по алфавиту. То же происходит с двумя D+записями. Когда рассматриваемая функция за+ канчивает сортировку, она фиксирует окончательный порядок индексов массива $math (0, 4, 2, 3, 1) и сортирует в этом порядке массив $student[], после чего оба массива оказываются отсортированными сначала по оценкам, а затем по именам.

Циклы foreach

Расширение цикла for называется цикл foreach и используется для обработки мас+ сивов с неизвестным числом элементов. Итерации в таком цикле повторяются вплоть до достижения конца массива. Данный цикл имеет два формата. Первый формат

foreach ($ArrayName As $ArrayItem){

выполнить код в данных фигурных скобках;

}

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

foreach ($crowd As $fan){

Добавить $fan в базу данных {}

}

Цикл обходит болельщиков и добавляет в базу по одному имени за раз. Не обяза+ тельно сообщать количество присутствующих на матче болельщиков, PHP может вы+ яснить это самостоятельно по количеству элементов в массиве $crowd.

Рассмотрим второй формат:

foreach ($ArrayName As $ArrayIndexValue => $ArrayItem){

выполнить код в фигурных скобках

}

Такая форма записи очень похожа на описанную выше, но она также делает дос+ тупными индексы массива. Рассмотрим вкратце работу цикла foreach на примере.

Практика Использование цикла foreach

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

1. Запустите редактор Web+страниц и введите следующий код:

<html>

<head><title></title></head>

<body>

216 Глава 4

<?

$states_of_the_USA = array ("Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico",

"New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming");

foreach($states_of_the_USA as $state_index => $state)

{

echo "<br>$state_index - $state";

}

?>

</body>

</html>

2.Сохраните данный файл как foreach.php и закройте его.

3.Откройте созданный файл в браузере и убедитесь, что на странице выведены все 50 штатов вместе с числами от 0 до 49 (рис. 4.14).

Рис. 4.14.

Логические операторы, циклы и массивы 217

Как это работает

Данная программа очень проста. Сначала создается массив с названиями всех 50 шта+ тов, который называется $states_of_the_USA:

$states_of_the_USA = array ("Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming");

Затем имя данного массива передается в качестве первого аргумента циклу foreach:

foreach($states_of_the_USA as $state_index => $state){

Второй и третий аргументы ++++++ имена созданных переменных, в которых содер+ жатся индексное значение и связанный с ним элемент массива соответственно. Код в фигурных скобках выполняется для каждого из 50 членов массива:

echo "<br>$state_index - $state";

}

В результате этого на странице построчно отображается каждое индексное значе+ ние и соответствующее ему название штата.

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

Во+вторых, указывать количество элементов массива не требуется. PHP определяет их количество автоматически, и в этом заключается главное преимущество цикла foreach. Это позволяет перемещаться по массиву, который может быть не упорядо+ ченным ни численно, ни по алфавиту. Кроме того, в массиве могут быть пропущен+ ные записи, но PHP проверяет не каждое индексное значение, а только те элементы, которые содержат какие+либо значения. Можно было бы включить следующий код, которые добавляет в массив штатов новый элемент:

$states_of_the_USA[100]="Atlantis";

Затем при повторном запуске сценария PHP добавил бы новое значение в конец Web+страницы, не проверяя при этом элементы с 50 по 99.

Резюме

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

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

218 Глава 4

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

Очевидно, что хотя циклы и массивы являются концептуально различными эле+ ментами языка программирования, в PHP они, по сути, тесно связаны. Циклы необ+ ходимы для выполнения повторяющихся операций, одна из таких операций ++++++ обра+ ботка больших связанных наборов индексированных переменных, каковыми являются массивы. В главе рассматривалось три типа циклов ++++++ while, do while и for. Каждый из них подходит для решения различных типов задач, поэтому выбор используемого цикла зависит от ситуации. В данной главе подробно рассматривались массивы и методы для работы с ними.

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

Упражнения

‘‘У нас есть Web+сайт, но информация на нем устарела. Он выглядит не очень при+ влекательно, но мы уже наняли дизайнера, которой переделает логотип, поэтому как только он закончит свою работу, трафик, вероятно, возрастет. Мы собираемся нани+ мать персонал для поддержки растущих запросов и хотим разместить на сайте про+ грамму для сбора резюме.’’

‘‘Посетители должны легко находить на сайте перечень вакансий, но эта ссылка не должна быть главным элементом страницы. Мы должны предоставить пользователю возможность искать работу и оставлять свою контактную информацию на сайте. Те, кто не имеет высшего образования, могут претендовать только на работы начального уровня в отделе продаж или отделе доставки. Заработные платы ни по одной из ва+ кансий для начала не превышают 20 000 долларов, на руководящих постах предлага+ ются поощрительные премии. Соискатели должны отправлять свои пожелания по за+ работной плате и иметь минимум двухлетний опыт работы. Желающие получить работу на руководящей позиции, в том случае если они не имеют докторской степени, должны иметь, по крайней мере, пятилетний опыт работы. Мы бы хотели, чтобы лю+ ди могли искать на сайте работу и подавать заявки на интересующие их позиции, а также чтобы они могли отправлять свои резюме и получать информацию о том, на какую работу они могут претендовать.’’

Именно так часто выглядят первоначальные требования к приложению со сторо+ ны заказчиков: малознакомый с программированием заказчик просит разработать программу для выполнения определенной функции.

Это упражнение определенно даст читателю некоторые практические навыки о том, как, начиная с формулировки проблемы, двигаться к созданию законченного продукта. Задача в данном случае заключается в том, чтобы изложить требования за+ казчика в более четкой форме и использовать возможности PHP для выполнения сбо+ ра и обработки информации, а также для выдачи ответа пользователям данного Web+ сайта. Чтобы выполнить упражнение, в дополнение к законченной программе следу+ ет включить следующие пункты:

Логические операторы, циклы и массивы 219

перечень всей необходимой информации в дополнение к уже представленной;

описание Web+страниц, которые вы будете разрабатывать, причины их разра+ ботки (зачем эти страницы нужны), и то, как пользователи будут взаимодейст+ вовать с ними;

краткое описание интеграции созданных страниц с существующим Web+сайтом.

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

Задание описано ++++++ можно приступать к проектированию.

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

5

Надежный и понятный код

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

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

Что означают эти качества? Надежную программу трудно вывести из строя даже при неверном обращении с ней. Такая программа способна справиться с разнообраз+ ными входными данными. А если по каким+либо причинам программа не может продолжать работу или получить желаемый результат, то она изящно останавливается, т.е. позволяет пользователю перейти к следующему логичному варианту и выводит какое+либо выразительное сообщение (и определенно не отображает сообщения об ошибках PHP или SQL). В дополнение к этому понятный код пишется с большим количе+ ством внутренней документации, так чтобы впоследствии, когда потребуется доработать код, создатель этого кода (или его коллега) мог легко вспомнить (или понять) первона+ чальные намерения. Понятный код это не просто работоспособный код, его структуры имеют определенный смысл и абстрагированы друг от друга настолько, что небольшое изменение одного участка кода вряд ли вызовет ошибки в других участках. Вместе данные качества улучшают программы и облегчают их последующее сопровождение.

В этой главе описаны основы тестирования, устранения неисправностей и отлад+ ки, а также использование функций обработки ошибок в PHP5. Кроме того, примеры

Надежный и понятный код 221

кода демонстрируют создание функции обработки строк для проверки данных, вве+ денных пользователем в форму, и использование для этого регулярных выражений, а также новую функциональность try/catch.

Тестирование и отладка

Отладка уже обсуждалась вкратце в главе 1 при рассмотрении темы устранения не+ исправностей в инсталляции PHP. В данной главе эта тема, а также формальный про+ цесс отладки рассмотрены подробно.

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

Обычно программисты пишут код и вставляют его, как уже было показано, в Web+ страницы либо генерируют HTML+код для Web+страниц с помощью оператора echo или из объектов. Чаще всего программисты пишут достаточное количество кода для выполнения осмысленного набора функций, а затем вызывают созданные страницы в браузере, чтобы проверить работу созданного кода.

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

Значения, нарушающие работу кода

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

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

Все данные, передаваемые браузером Web+серверу, форматируются как строки. Например, число 1995 может быть годом или ценой, но при передаче Web+серверу посредством HTTP+запроса оно поступает в PHP+процессор в виде строки. Строка может быть пустой или состоять из любого количества символов. Если программа ожидает число, то все в порядке, поскольку PHP весьма снисходительно относится к типам данных. Однако если программа ожидает строку определенной длины и не получает ее, то может возникнуть проблема.

222 Глава 5

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

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

Могут также возникать и другие проблемы, такие как ввод значений, которые по+ падают в соответствующий диапазон или имеют необходимый тип данных, но все равно по какой+либо причине непригодны для использования в программе. Напри+ мер, длина e+mail+адреса может быть ограничена в базе данных до 100 символов; что же произойдет, если пользователь введет адрес, состоящий из 101 символа? И что про+ изойдет, если пользователь забудет вставить символ @ в свой адрес? Передаваемые серверу данные в любом случае остаются строковыми и внешне могут выглядеть как e+mail+адрес, но ошибки такого рода все равно могут создавать проблемы.

Поэтому можно начать тестирование приложения с того, чтобы убедиться, что передаваемая строка действительно форматируется как строка, число, дата или зна+ чение другого типа данных, а затем продолжать тестирование, проверяя, попадает ли данное значение в необходимый диапазон. После этого следует выполнить другие тесты, которые гарантируют, что переданная строка имеет правильную длину, а воз+ можно даже содержит некоторые специальные символы, подходящие для того типа данных, в который она будет преобразована. Все эти проверки кажутся весьма трудо+ емкими, однако реальность такова, что пользователи часто вводят неверные данные и данные, которые кажутся правильными, но не могут быть правильно обработаны (например ‘‘три’’ вместо 3), поэтому дополнительные усилия и затраты времени, не+ обходимые для тестирования приложения, окупятся сторицей.

Основные типы ошибок

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

Когда приложение не может найти или открыть какой+либо файл или подклю+ читься к базе данных, возникают ошибки другого типа. Эти ошибки называются ошиб* ками времени выполнения (runtime errors), поскольку возникают во время выполнения программы. PHP может программно обнаруживать и такие ошибки, а также генери+ ровать соответствующие сообщения о них.

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

Соседние файлы в папке web - tec