Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

PHP. Доступ к базам данных.

Лабораторная работа №6

 

Общие сведения

Существуют два основных способа хранения данных: в двумерных (обычных) файлах и в базах данных. Двумерный файл может иметь множество форматов, но в общем случае под двумерным (flat) файлом будем понимать простой текстовый файл. Этот способ столь же прост, сколь и ограничен. Если приходится иметь дело с достаточно большим объемом информации, вероятно, лучше воспользоваться базами данных.

Системы управления реляционными базами данных (СУРБД) могут обеспечить более быстрый доступ к данным, чем двумерные файлы. А MySQL, система управления базами данных, обладает одними из самых высоких показателей производительности среди всех СУРБД.

· В СУРБД можно легко отправлять запрос для извлечения наборов данных, со­ответствующих определенным критериям.

· СУРБД обладают встроенными механизмами обработки конкурирующих обращений, что позволяет программисту не беспокоиться об этом.

· СУРБД обеспечивают произвольный доступ к данным.

· СУРБД обладают встроенными системами определения прав доступа. MySQL обладает особенно большими возможностями в этой области.

Вероятно, главная побудительная причина использования СУРБД заключается в том, что все (или, по меньшей мере, большинство) функциональные возможности, требуемые от системы хранения данных, в ней уже реализованы. Конечно, можно было бы создать собственную библиотеку РНР-функций, но зачем же заново изобретать колесо?

Доступ к базам данных.

Подготовка базы. Перед организацией системы доступа к базам данных, необходимо иметь эти базы. Далее рассматривается создание учебной базы данных, используемой в примерах.

Запустив PHPMyAdmin, выберем базу данных books:

Для соединения РНР-сценариев с MySQL потребуется настроить пользователя. В этом случае нужно применить принцип наименьших привилегий: зачем права сценариям?

В большинстве случаев сценариям понадобится проводить над строками таблиц только такие операции: SELECT, INSERT, DELETE и UPDATE.

Для БД books пользователь с такими привилегиями нами уже создан – это пользователь bookvoed с паролем 123.

(He забывайте о безопасности! В реальной работе такой пароль, конечно, никуда не годится).

В нашей базе данных есть таблица books, ее мы и будем использовать для дальнейшей работы.

Как работает архитектура Web-баз данных. Распишем ее по шагам:

1. Web-браузер пользователя выдает HTTP-запрос определенной Web-страницы. Например, пользователь ищет в Book все книги, написанные Майклом Морганом, используя HTML-форму. Страница с результатами поиска будет называться results.php.

2. Web-сервер принимает запрос на results.php, извлекает этот файл и передает на обработку механизму РНР.

3. Механизм РНР приступает к разбору сценария. Сценарий содержит команду соединения с базой данных и выполнения запроса (поиска книг). РНР открывает соединение с MySQL-сервером и отправляет соответствующий запрос.

4. Сервер MySQL принимает запрос к базе данных, обрабатывает его и отправляет результат (список книг) обратно механизму РНР.

5. Механизм РНР завершает выполнение сценария, что обычно включает в себя форматирование результатов запроса в HTML. После этого результат в виде HTML возвращается Web-серверу.

6. Web-сервер пересылает HTML в браузер, и пользователь имеет возможность просмотреть запрошенный список книг.

У нас имеется база данных MySQL, поэтому можем подготовить код РНР, чтобы выполнялись предыдущие шаги. Начнем с поисковой формы. Это простая HTML-форма. Код для этой формы показан в листинге 1 (сохраняйте эти файлы в созданной вами директории, или создайте ее снова, как описано в работе 1).

Листинг 1. search.html — поисковая страница для базы данных Book

<html><head><title>Поиск книг в каталоге</title> </head><body>

<hl>Поиск книг в каталоге</hl>

<form action="results.php" method="post">

Выберите тип поиска:<br>

<select name="searchtype">

<option value="author">Автор

<option value="title">Название

<option value="isbn">ISBN </select> <br><br>

Введите строку поиска:<br>

<input name="searchterm" type=text> <br><br>

<input type=submit value="Поиск"> </form>

</body> </html>

После того как пользователь нажмет на кнопке Поиск, вызывается сценарий results.php. Все это представлено в листинге 2. Далее мы рассмотрим, что делает упомянутый сценарий и как он работает.

Листинг 2. results.php - извлечение результатов запроса и форматирование их

<html><head><title>Результат поиска книги</title></head>

<body>

<hl> Результат поиска книги </hl>

<?

trim($searchterm);

if (!$searchtype ||!$searchterm) {

echo " Вы не ввели критерии поиска. Вернитесь назад и повторите ввод.";

exit; }

$searchtype = addslashes($searchtype);

$searchterm = addslashes($searchterm);

@$db = mysql_pconnect("localhost", "bookvoed", "123");

if (!$db) {

echo "Ошибка: Нет соединения с БД. Повторите попытку позже.";

exit; }

mysql_select_db("books");

mysql_query ("set character_set_client='cp1251'");

mysql_query ("set character_set_results='cp1251'");

mysql_query ("set collation_connection='cp1251_general_ci'");

$query = "select * from books where ".$searchtype." Like '%".$searchterm."%'";

$result = mysql_query($query);

$num_results = mysql_num_rows($result);

echo "<p>Количество найденых книг: ".$num_results."</p>";

for ($i = 0; $i <$num_results; $i ++) {

$row = mysql_fetch_array($result);

echo "<p><strong>".($i+1).". Название: ";

echo htmlspecialchars(stripslashes($row["title"]));

echo "</strong><br>Автор: ";

echo htmlspecialchars (stripslashes($row["author"]));

echo "<br>ISBN:";

echo htmlspecialchars (stripslashes($row["isbn"]));

echo "<br>Цена: ";

echo htmlspecialchars (stripslashes($row["price"]));

echo "</p>"; }

?>

</body> </html>

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

1. Проверка и фильтрация данных, исходящих от пользователя.

2. Установка соединения с требуемой базой данных.

3. Передача запроса в базу данных.

4. Получение результатов.

5. Представление результатов пользователю.

То же самое делает и сценарий results.php, и сейчас мы исследуем каждый из этих этапов.

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

trim($searchterm);

Следующий этап — убедиться, что пользователь указал критерий и тип поиска. Заметьте, это проверяется лишь тогда, когда критерий поиска не содержит лишние пробелы. Если поменять эти этапы местами, может возникнуть ситуация, когда критерий вроде и введен, сообщения об ошибке быть не должно, однако критерий содержит только пробелы, которые полностью удаляются функцией trim():

if (!$searchtype ||!$searchterm) {

echo " Вы не ввели критерии поиска. Вернитесь назад и повторите ввод.";

exit; }

В этом случае выдается сообщение о том, что критерий поиска не введен.

Мы проверили переменную $searchtype даже в том случае, когда она поступает из оператора SELECT. Вас может заинтересовать, зачем проверять входные данные. Не забывайте, что база данных может иметь не один интерфейс. Например, Amazon располагает большим количеством филиалов, которые используют свои поисковые интерфейсы. Вследствие того, что пользователи могут заходить с разных рабочих станций, возникает и потенциальная угроза безопасности.

В случае задействования данных, которые вводят другие пользователи, необходимо тщательно фильтровать вводимые данные от управляющих символов. Если записывать данные, введенные пользователем, в базу данных типа MySQL, следует вызывать addslashes(), а при возврате пользователю выходных данных — stripslashes().

В нашем случае к критерию поиска применяется функция addslashes():

$searchterm = addslashes ($searchterm);

К данным, исходящим из базы, применяется stripslashes(). Введенные данные не содержат косых линий, равно как и управляющих символов. То есть вызов stripslashes() не поможет. При построении Web-интерфейса для базы данных велики шансы того, что потребуется вносить данные о новых книгах, а детали, внесенные пользователем, могут содержать специальные символы. Сохраняя их в базе данных, мы обращаемся к addslashes(), а это означает, что при извлечении данных необходимо будет вызывать stripslashes().

Функцию htmlspecialchars() применяют для кодировки символов, которые в HTML имеют особое значение. В наших тестовых данных нет амперсандов (&), знаков "меньше" (<), "больше" (>), двойных кавычек ("), однако в названиях многих замечательных книг может повстречаться амперсанд. Использование этой функции страхует от грядущих ошибок.

Установка соединения. Для подключения к серверу MySQL в сценарии есть такая строка:

@$db = mysql_pconnect("localhost", "bookvoed", "123");

Для подключения к базе данных используется функция mysql_pconnect() с прототипом:

int mysql_pconnect ([string host [:port] [:/socketpath]],

[string user], [string password]);

Потребуется указать имя узла (host), на котором размещен сервер MySQL, имя пользователя (user), чтобы войти в него, и пароль (password). Все это необязательно и если не указать все вышеперечисленное, функция воспользуется значениями по умолчанию — локальная машина вместо узла, имя пользователя, под которым запущен РНР, и пустой пароль.

При успехе функция вернет идентификатор связи с базой данных (который следует сохранить для дальнейшего использования), а при неудаче — значение false. Результат не стоит игнорировать, поскольку без соединения с базой данных работа невозможна. Это делает следующий код:

if (!$db) {

echo " Ошибка: Нет соединения с БД. Повторите попытку позже."; 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 соединений, а MySQL — только 100. В особо напряженное время соединений может не хватить. Поэтому лучше всего настроить параметры так, чтобы у каждого процесса Web-сервера было свое соединение, конечно, с оглядкой на технические возможности применяемых аппаратных средств.

Выбор базы данных. Работая с MySQL, необходимо указывать, какая база данных нужна. Это может сделать РНР-функиия mysql_select_db():

mysql_select_db("books");

Прототип этой функции выглядит так:

int mysql_select_db(string database, [int database_connection]);

В результате будет использоваться база данных с именем database. Можно также использовать соединение с базой данных, для которого требуется выполнить эту операцию (в нашем случае $db), однако, если его не указать, будет использоваться последнее открытое соединение. Если открытое соединение не существует, оно открывается по умолчанию, как если бы вызывалась mysql_connect().

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

Указываем, что в БД используется кодировка cp1251.

mysql_query ("set character_set_client='cp1251'");

mysql_query ("set character_set_results='cp1251'");

mysql_query ("set collation_connection='cp1251_general_ci'");

 

Теперь необходимо настроить запрос:

$query = "select * from books where ".$searchtype." like '%".$searchterm."%'";

В этом случае будет отыскиваться значение, введенное пользователем ($searchterm), в поле, которое указал пользователь ($searchtype). Обратите внимание на то, что мы употребили like, отдав ему предпочтение перед equal — толерантность никогда не бывает излишней. Не забывайте, что запрос, отправляемый вами в MySQL, не требует в конце точки с запятой, в отличие от запроса, который вводится в среде монитора MySQL.

Теперь можно выполнить запрос:

$result = mysql_query ($query);

Прототип функции mysql_query() таков:

int mysql_query(string query, [int database_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), чтобы извлечь из него некоторую пользу.

Получение результатов запроса. Разнообразие функций дает возможность получить результат различными способами. Идентификатор результата — это ключ доступа к строкам, возвращенным запросом, которых может быть нуль, одна и более.

В нашем примере использовались две функции: mysql_numrows() и mysql_fetch_array().

Функция mysql_numrows() сообщает количество строк, которые возвращает запрос В нее следует передать идентификатор результата:

$num_results = mysql_num_rows($result);

Это полезно знать, если планируется обрабатывать или отображать результаты. Зная их количество, можно организовать цикл:

for ($i=0; $i <num_results; $i++)

{ // обработка результатов

}

На каждой итерации цикла происходит вызов mysql_fetch_array() Цикл не будет выполняться, если нет строк. Эта функция берет каждую строку из списка результата и возвращает ее в виде ассоциативного массива, с ключом как именем атрибута и значением как соответствующим значением массива.

$row = mysql_fetch_array($result);

Имея $row в ассоциативном массиве, можно пройти каждое поле и отобразить его:

echo "<br>ISBN: ";

echo stripslashes($row["isbn"]);

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

Существуют несколько вариантов получения результата из идентификатора результата. Вместо ассоциативного массива можно воспользоваться нумерованным массивом, применив 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(), так что лучше использовать одну из них

Отсоединение от базы данных. Для закрытия непостоянного соединения применяется функция:

mysql_close(database_connect±on);

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

 

 

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

Листинг 3. newbook.html — HTML-код страницы добавления новых книг

<html><head><title>Добавление новых книг</title> </head> <body>

<hl>Добавляем новую книгу</hl>

<form action="insert_book.php" method="post"> <table border=0>

<tr><td>ISBN</td><td><input type=text name=isbn maxlength=13 size=13><br></td> </tr>

<tr><td>Author</td><td> <input type=text name=author maxlength=30 size=30><br></td> </tr>

<tr><td>Title</td><td> <input type=text name=title maxlength=60 size=30><br></td> </tr>

<tr><td>Price $</td><td><input type=text name=price maxlength=7 size=7><br></td> </tr>

<tr><td colspan=2><input type=submit value="Добавить"></td></tr>

</table>

</form></body></html>

Результаты заполнения этой формы передаются в insert_book.php, а сценарий выполняет определенную аутентификацию и пытается записать данные в базу данных. Код для сценария представлен в листинге 4.

Листинг 4. insert_book.php — сценарий записывает новые книги в базу данных

<html><head><title> Результат добавления книги</title></head> <body>

<hl>Результат добавления книги</hl><br>

<?

if (!$isbn ||!$author ||!$title ||!$price)

{echo "Вы не ввели все необходимые данные.<br>"

."Вернитесь назад и повторите попытку снова."; exit; }

$isbn = addslashes($isbn);

$author = addslashes($author);

$title = addslashes($title);

$price = doubleval($price);

@$db = mysql_pconnect("localhost", "bookvoed", "123");

if (!$db) {

echo " Ошибка: Нет соединения с БД. Повторите попытку позже."; exit;}

mysql_select_db ("books");

mysql_query ("set character_set_client='cp1251'");

mysql_query ("set character_set_results='cp1251'");

mysql_query ("set collation_connection='cp1251_general_ci'");

$query = "insert into books values

('".$isbn."', '".$author."', ' ".$title."', '".$price."')";

$result = mysql_query($query);

if ($result)

echo mysql_affected_rows().". Книга добавлена в базу данных";

?>

</body> </html>

После изучения кода insert_book.php станет ясно, что он во многом похож на код сценария для извлечения данных из базы. Мы проверяем, чтобы все поля формы были заполнены и отформатированы с помощью addslashes() перед внесением данных в базу.

$isbn = addslashes($isbn); $author = addslashes($author);

$title = addslashes($title); $price = doubleval($price);

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

Мы снова соединяемся с базой данных, используя mysql_pconnect(), и настраиваем запрос. В данном случае это INSERT.

$query = "insert into books values

('".$isbn."', '".$author."', '''.$title."', '''.$price.''')";

$result = mysql_query($query);

Выполнение происходит не без помощи mysql_query().

Одно существенное различие между INSERT и SELECT заключается в использовании mysql_affected_rows():

echo mysql_af£ected_rows(). " book inserted into database.";

В предыдущем сценарии функция mysql_num_rows() применялась для определения количества строк, которые будет возвращать SELECT. При написании запросов, которые изменяют базу данных, например, INSERT, DELETE, UPDATE, следует использовать mysql_affected_rows().

Мы рассмотрели основы использования баз данных MySQL из РНР. Взглянем еще на некоторые полезные функции, не упомянутые ранее.

Рассмотрим кратко несколько полезных функций PHP-MySQL.

Освобождение ресурсов. Если во время выполнения сценария возникают проблемы, связанные с нехваткой памяти, пригодиться функция mysql_free_result(). Вот ее прототип:

int mysql_free_result(int result);

Она вызывается с идентификатором результата:

mysql_free_result($result);

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

Создание и удаление баз данных. Для создания новой базы данных MySQL из РНР-сценария применяется функция 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.

 

Задание

1. Модифицируйте файл index.html в вашей папке таким образом, чтобы с его помощью можно было открывать страницы добавления и поиска книг.

2. Напишите PHP – скрипт, позволяющий выбрать все записи из таблицы books.

 

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...