Некоторые улучшения в организации работы с данными
Рассмотрим код:
<?php
if (!($row = sql_fetch_row ($result))) {
print "Ошибка: не найдено ни одного ряда";
exit;
}
do {
print "$row[0]: $row[1]\n<br>\n";
}
while ($row = sql_fetch_row ($result));
?>
В этом коде возможны по крайней мере два улучшения:
Задействовав функцию sql_fetch_row(), данный кусок кода предлагает косвенную проверку выборки на наличие хотя бы одного ряда данных. Но существует прямой способ - это подсчёт количества рядов в выборке $result функцией sql_num_rows():
<?php
if (sql_num_rows ($result) <= 0) {
print "Ошибка: не найдено ни одного ряда";
exit;
}
while ($row = sql_fetch_row ($result)){
print "$row[0]: $row[1]\n<br>\n";
}
?>
Исчезает необходимость в использовании do..while, ибо для проверки на "ноль рядов" функция sql_num_row() не выдёргивает первый ряд в $row, и указатель по-прежнему установлен на начало.
Вторая проблема нашего кода - это использование функции sql_fetch_row() для получения рядов. Как результат своей работы эта функция возвращает лишь пронумерованный массив. Однако существует ещё и функция sql_fetch_array(), которая возвращает два массива: пронумерованный и ассоциативный:
<?php
$row = sql_fetch_array ($result);
print $row[1]; // Второй столбец
print $row[name]; // Столбец name - имя
?>
Примечание: Существуют разные точки зрения на целесообразность использования одинарных кавычек при вставке строковых аргументов. В приведённом примере (столбец name) и далее по статье они не используются.
Какая из функций более удобна для разработчика? Ассоциативные массивы позволяют редактору кода ясно и однозначно понять, какая именно выборка из БД будет осуществляться в каждом конкретном случае. Например:
<?php
if (sql_num_rows ($result) <= 0) {
print "Ошибка: не найдено ни одного ряда";
exit;
}
while ($row = sql_fetch_array ($result)) {
print "$row[name]: $row[phone_number]\n<br>\n";
}
?>
Ошибки SQL: запрашивается не то, что нужно
Язык Структурированных Запросов (SQL) был специально разработан для запросов и получения данных из таблиц в БД. Идея языка заключается в отсеивании данных ненужных вам (средствами SQL) и получении только тех, которые вам действительно необходимы для дальнейшей обработки (например, средствами PHP). Обработка выборки из БД средствами PHP - тоже является ошибкой.
Классический пример эффективного применения SQL-запросов - использование условия WHERE в синтаксисе SQL.
Рассмотрим пример кода, производящего выборку и выводящего список имён и телефонов всех пользователей с id равным 5:
<?php
// В предыдущих строках
// устанавливается соединение, и $conn
// определяется как дескриптор соединения.
$statement = "SELECT name, phone, id FROM samp_table";
$result = @sql_query ($statement, $conn);
if (!$result) {
die (sprintf ("Ошибка [%d]: %s", sql_errno (), sql_error ()));
}
if (@sql_num_rows ($result) <= 0) {
die ("Получено ноль результатов");
}
while ($row = @sql_fetch_array ($result)){
if ($row[id] & 5) {
print "Имя: $row[name]\n<br>\n";
print "Телефон: $row[phone]\n<br>\n";
break;
}
}
?>
Данный код имеет следующие недоработки: для поиска по всей БД используется PHP; при работе с БД малого размера на это можно и не обращать внимания, но с ростом БД вы обязательно заметите резкое падение скорости работы скриптов.
Выход прост: включите в SQL-запрос условие WHERE:
<?php
$statement = "SELECT name, phone FROM samp_table";
$statement .= " WHERE id='5'";
WHERE позволит применить более строгие критерии выборки. Фильтром в данном случае будет являться значение аргумента. В нашем примере это "id=5".
Получив нужную вам выборку, вы используете PHP для простого вывода результатов:
<?php
if (@sql_num_rows ($result) != 1) {
die ("Получено неверное количество рядов");
}
$row = @sql_fetch_array ($result);
print "Имя: $row[name]\n<br>\n";
print "Телефон: $row[phone]\n<br>\n";
?>
Обработка результатов выборки средствами PHP
Нередко программист намеренно не сортирует выборку при запросе, перекладывая эту работу на PHP. Такой подход неэффективен, ибо сортировка средствами SQL проходит намного быстрее, чем в PHP.
Для сортировки результатов рекомендуем применять синтаксис SQL (ORDER BY), а не PHP-функцию ksort().
Рассмотрим пример использования ksort() для сортировки выборки по имени (name):
<?php
$statement = "SELECT name, email, phone FROM some_table ";
$statement .= "WHERE name IS LIKE '%baggins'";
$result = @sql_db_query ($statement, "samp_db", $conn);
if (!$result) {
die (sprintf ("Ошибка [%d]: %s", sql_errno (),sql_error ()));
}
while ($row = @sql_fetch_array ($result)){
$matches[ $row[name] ] = array ($row[email], $row[phone]);
}
ksort ($matches);
?>
Возникает вопрос: а почему бы ни провести сортировку результатов во время выборки? Это избавит нас от необходимости проходить по всему массиву с результатами дважды.
Итак, убираем ksort() и исправляем SQL-запрос, добавив ORDER BY:
<?php
$statement = "SELECT name, email, phone FROM some_table ";
$statement .= "WHERE name IS LIKE '%baggins' ORDER BY name";
?>
Передача данных от клиента к серверу и обратно. Протокол HTTP
Основной протокол передачи гипертекстовых данных – это HTTP. HTTP основывается на запросах/ответах. При этом запрашивающая программа - клиент устанавливает связь с программой- сервером и посылает запрос серверу в следующей форме:
метод запроса, URI, версия протокола, сообщение, содержащее управляющую информацию запроса, информацию о клиенте и тело сообщения.
Запрос создается браузером клиента. Когда пользователь набирает в браузере URL-адрес: http:bsu.by/my.php вот что при этом происходит:
Браузер разбирает URL-адрес и решает следующее:
-Использовать протокол HTTP.
-Извлечь запрошенный ресурс с компьютера, находящегося на bsu. by.
-Получить информационный ресурс, известный, как /my.php.
На основе данной информации создается запрос HTTP, выглядящий следующим образом:
GET /my.php HTTP/1.1
Accept: image/gif, image/png, image/jpeg, */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0;
Windows XP; .NET CLR 1.1.4322)
Host:bsu.by
Connection: Keep-Alive
Вот что эти строки значат:
GET — метод HTTP который означает: "Дай информацию, находящуюся в /му.php, и вышли ее, используя протокол HTTP 1.1".
Accept — "я могу понимать графическую информацию в следующих форматах".
Accept-Language — "язык, который я понимаю — английский, американский ". Accept-Encoding — "мне можно отправлять данные в сжатом виде, поскольку я понимаю типы сжатия gzip и deflate".
User-Agent — "тип моего браузера — Microsoft Explorer 8, выполняющийся под управлением Windows XP".
Host — "доставь мне информацию /my.php с компьютера, находящегося на хосте feedster.com".
Connection: Keep-Alive — "держи подключение HTTP открытым, пока браузер не закроет его". Это повышает производительность, поскольку соединение не нужно закрывать и снова открывать для каждого подключения. Без Keep-Alive Web-страница будет иметь множество подключений.
Когда Web-сервер получает подобный запрос, он должен просмотреть информацию на сервере, которая представлена /my. php.
В конце запроса помещается его тело.
Сервер отвечает на запрос сообщением, содержащим строку статуса (включая версию протокола и код статуса - успех или ошибка), за которой следует MIME-подобное сообщение, включающее в себя информацию о сервере, метаинформацию о содержании ответа, и, само тело ответа. Ответ (response) сервера посылается клиенту (браузеру) в виде:
НТТР/1.1 200 0К
Date: Моп, 08 Dec 2003 16:46:40 GMT
Server: Apache/1.3.27 (Unix) mod_throttle/3.1.2 PHP/4.3.2
X-Powered-By: PHP/4.3.2
X-Accelerated-By: PHPA/1.3.3r2
Connection: close
Content-Type: text/html; charset=utf-8
<html lang="en-US" xml:lang="en-US" «nlns="http://www.w3.org/1999/xhtml">
<head>
<script>
HTTP-ответ состоит из двух частей. В начале идет порция сведений о самой запрошенной информации - заголовок ответа (response header). Затем идет пустая строка и далее — сама запрошенная информация. Эта вторая часть называется телом (body). Вот что означают части заголовка:
HTTP/1.1 — первая строка сообщает клиенту, что информация будет отправлена по протоколу HTTP версии 1.1. Код 200 состояния HTTP означает: "Все хорошо, документ найден и сейчас будет отправлен".
Date — сообщает клиенту дату, установленную на сервере, с которого поступает информация. Стандартный часовой пояс — GMT, то есть время по Гринвичу.
Server — каков тип сервера, предоставляющего информацию.
X-Powered-By — каким инструментом поддерживается сервер (конечно, РНР).
X-Accelerated-By — какой инструмент повышает производительность сервера (эти два Х-заголовка не обязательны и специфичный для конкретной конфигурации сервера).
Connection — сообщает клиенту, что соединение будет закрыто после того, как сервер завершит отправку информации.
Content-Type — сообщает клиенту, какой тип содержимого будет отправлен. В дополнение также указывается набор символов.
Клиентские методы HTTP
В HTTP метод клиента определяет запрос, отправленный от Web-клиента, либо РНР-сценария, HTTP-серверу. Существуют три основных типа запросов:
GET-запросы. Когда вы хотите только получить информацию от источника HTTP, то можете сделать это методом GET. Получить информацию можно из файла, либо от исполняемой программы на Web-сервере с указанным URL-адресом. Привлекательность HTTP состоит в том, что запрос GET делает выполнение программы таким же простым, как извлечение файла.
POST-запросы. Когда вы хотите отправить информацию от клиента Web-серверу, то используете запрос POST. Обычно это имеет место, когда вы отправляете содержимое Web-формы Web-серверу.
HEAD-запросы. Когда вы хотите получить информацию о запрошенном URL, но не информацию самого URL, то используете запрос HEAD.
По методу GET контент запроса посылается через поля формы или через строку URL, по методу POST – через поля формы. Запросы можно создать и отправить вручную с помощью средств JavaScript, а получить обратно с помощью методов PHP.
Простой способ просмотреть HTTP запросы и ответы состоит в установке плагина для браузера Firefox, который называется HttpFox и доступен для свободного скачивания.
Ниже приведен пример работы HttpFox для сервера localhost.
Обработка HTML-форм
Одно из главнейших достоинств PHP – это реализация возможности работы с формами HTML для отправки и получения информации. Формы используется почтовыми службами, электронными магазинами и многими другими типами сайтов. Формы – удобный способ получения информации от посетителей сайта. Пример тому – гостевая книга, – которая обеспечивает обратную связь с посетителями и разработчиками сайта.
Формой называется конструкция, состоящая из поименованных элементов, заключенных между HTML-тэгами <form...> n</form>. В качестве элементов формы могут выступать поля ввода текста, кнопки, выпадающие меню, переключатели, квадратики для отметки галочкой checkbox, а также картинки формата jpg или gif. Каждый элемент формы может иметь свое имя. При этом каждый элемент клиентской формы может пересылаться на сервер и становится доступен серверным программам на PHP.
Наиболее важным свойством формы является то, что в ее заголовке в открывающем тэге <form...> можно указать адрес какого-либо файла. В этом случае при загрузке этого файла в программный код, если он будет там присутствовать, передадутся значения всех переменных, установленных в этой форме, в частности, значения всех элементов формы, как если бы эти значения были установлены в программе, расположенной в самом загружаемом файле. Таким образом, можно передавать значения переменных между различными web-страницами, используя их в программном коде.
Если в конфигурационном файле РНР - php.ini - параметр register_globals установлен в on, имена передаваемых переменных соответствуют тем именам, которые были даны элементам формы, а значения - соответственно значениям этих элементов: для поля ввода текста - введенному тексту, для переключателя или checkbox - True при отмеченном и False при неотмеченном, для рисунка - координаты указателя мыши относительно верхнего левого угла изображения. Кроме того, переменные, передаваемые через форму, помещаются в ассоциативные массивы $_POST_ или $_GET. Содержимое поля ввода текста <input type=text name=’myname’ size=30> окажется в элементе $_POST['myname']) или $_GET['myname']). Различие между двумя методами состоит в том, что при передаче данных методом GET эти данные отображаются в адресной строке браузера, а при использовании метода POST - нет. Переменные $_POST и $_GET доступны и во всех функциях, расположенных в программе РНР, т. е. являются глобальными. Способ передачи данных через глобальные переменные является основным, поскольку в последних версиях PHP register_globals установлен в off по умолчанию. Ниже показаны обычно используемые суперглобальные переменные PHP: $_GET[], $_POST[], $_REQUEST[], $_COOKIE[], $_FILES[], $_SERVER[], $_ENV[], $_SESSION[].