Курсовые работы / Разработка Web API для организации поиска в базах данных MySQL
.pdfМОСКОВСКИЙ ЭНЕРГЕТИЧЕСКИЙ ИНСТИТУТ (ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ)
ИНСТИТУТ АВТОМАТИКИ И ВЫЧИСЛИТЕЛЬНОЙ ТЕХНИКИ КАФЕДРА ПРИКЛАДНОЙ МАТЕМАТИКИ
Курсовая работа
Разработка Web API для организации поиска в базах данных MySQL.
Выполнил студент группы А-13-08
каф. Прикладной Математики Захаров Антон
Преподаватель Сидорова Наталья Петровна
Научный руководитель Чибизова Наталья Владимировна
Москва,2011
Содержание.
I. Постановка задачи |
2 |
Определения ключевых понятий |
2 |
Постановка задачи |
2 |
II. Библиотека для работы с базами данных MySQL |
3 |
Система управления базой данных MySQL |
3 |
Описание библиотеки |
4 |
Установка соединения с базой данных |
5 |
Выполнение SQL запросов |
6 |
Пример использования |
9 |
III. Библиотека для поиска в базах данных MySQL |
10 |
Полнотекстовый поиск в MySQL |
10 |
Описание библиотеки |
12 |
Формирование поисковых запросов |
14 |
Пример использования |
18 |
Список литературы |
21 |
1
Часть I.
Постановка задачи.
Определения ключевых понятий.
Для начала дадим определения основных понятий, с которыми будем сталкиваться по ходу данной работы.
API (интерфейс программирования приложений) – набор готовых классов, процедур, функций, структур и констант, предоставляемых приложением (библиотекой, сервисом) для использования во внешних программных продуктах.
Поисковая система – программно-аппаратный комплекс с вебинтерфейсом, предоставляющий возможность поиска информации в Интернете. Под поисковой системой обычно подразумевается сайт, на котором размещён интерфейс системы.
Словоформа (форма слова) – слово в узком смысле, то есть обладающая признаками слова цепочка фонем, формально отличающаяся от другой.
Постановка задачи.
Внаши дни умение быстро найти необходимую информацию ценится особенно высоко. И наиболее ярко это можно видеть на примере одной из крупнейших поисковых систем в мире «Яндекс»: только за сентябрь 2011 года было обработано свыше 3 млрд. поисковых запросов. И это всего лишь 1,7% от мирового количества!
Поисковые системы на сегодняшний день дают человеку возможность получить практически любые сведения об окружающем мире. Однако, перед разработчиком веб-сайтов нередко возникает задача реализовать подобный функционал для осуществления поиска по контенту сайта. Тут бы и пригодилась библиотека, предоставляющая нужную функциональность, при этом позволяющая абстрагироваться от того, как именно эта функциональность реализована.
Вданной работе я постараюсь разработать Web API для организации полнотекстового поиска в базах данных MySQL. В качестве языка программирования будет использовать PHP, интенсивно применяемый для разработки веб-приложений.
2
Часть II.
Библиотека для работы с базами данных MySQL.
Система управления базами данных MySQL.
MySQL – свободная система управления базами данных (СУБД). MySQL является собственностью компании MySQL AB, осуществляющей разработку
иподдержку приложения. Распространяется под GNU General Public License и под собственной коммерческой лицензией, на выбор. Помимо этого компания MySQL AB разрабатывает функциональность по заказу лицензионных пользователей, именно благодаря такому заказу почти в самых ранних версиях появился механизм репликации.
MySQL характеризуется большой скоростью, устойчивостью и лёгкостью в использовании, является решением для малых и средних приложений. Наряду с Oracle Database это одна из самых быстрых СУБД на сегодняшний день. Распространение СУБД MySQL на основе GPL и высокая скорость обработки запросов привело к тому, что эта база данных стала стандартом в услугах сетевого хостинга. Обычно MySQL используется в качестве сервера, к которому обращаются локальные или удалённые клиенты, однако в дистрибутив входит библиотека внутреннего сервера, позволяющая включать MySQL в автономные программы.
Гибкость СУБД MySQL обеспечивается поддержкой большого типа таблиц: пользователи могут выбрать как сверхбыстрые таблицы типа MyISAM, поддерживающие полнотекстовый поиск, так и более медленные, но чрезвычайно устойчивые таблицы InnoDB, поддерживающие транзакции на уровне отдельных записей. Благодаря открытой архитектуре и GPL лицензированию в СУБД MySQL постоянно появляются новые типы таблиц.
MySQL портирована на большое количество платформ: Windows, BSDi, Linux, Mac OS X, NetBSD и др. Важно отметить, что на официальном сайте СУБД для свободной загрузки предоставляются не только исходные коды, но
иоткомпилированные и оптимизированные под конкретные операционные системы готовые исполняемые модули СУБД MySQL.
Исторически СУБД MySQL разрабатывалась для web-сайтов и обеспечивала быструю индексацию данных в хранилищах и оптимизацию последовательного доступа к данным (система хранения ISAM).
Преимущества СУБД MySQL.
Основные преимущества:
высокая производительность
масштабируемость
надёжность
простота использования, простота внедрения
3
открытая и модульная разработка
низкие совокупные затраты (платить нужно только при потребности в поддержке)
MySQL включает API для большого количества языков программирования (Delphi, C, C++, Эйфель, Java, Лисп, Perl, PHP, Python, Ruby, Smalltalk, Tcl, библиотеки для языков платформы .NET)
поддержка MySQL присутствует на большинстве хостингов в Рунете
кроссплатформенность (UNIX системы и среда Microsoft Windows)
гибкая политика лицензирования
Описание библиотеки.
Прежде чем переходить к написанию методов API для осуществления поиска в базах данных MySQL опишем методы установки соединения и выполнения запросов. Все методы для удобства объединим в класс DB.
|
|
|
|
|
Открытые свойства класса DB. |
|
||
|
|
|
|
|
|
|
|
|
|
Свойство |
|
Тип |
|
|
|
Описание |
|
|
|
|
|
|
|
|
|
|
|
$connection |
|
resource |
|
|
Указатель на соединение с MySQL |
|
|
|
$dsn |
|
array |
|
|
Данные соединения: |
|
|
|
|
|
|
|
|
host – спецификация сервера (имя_сервера*:порт+) |
|
|
|
|
|
|
|
|
database – название базы данных |
|
|
|
|
|
|
|
|
username – имя пользователя |
|
|
|
|
|
|
|
|
password – пароль для логина |
|
|
|
|
|
|
|
Открытые методы класса DB. |
|
||
|
|
|
|
|
|
|
||
|
Метод |
|
|
|
Описание |
|
||
|
|
|
|
|
|
|
||
|
connect($dsn) |
|
|
|
Установка соединения с базой данных MySQL. |
|
||
|
|
|
|
|
|
|
array $dsn – данные соединения. |
|
|
disconnect() |
|
|
|
|
|
Отсоединение от базы данных MySQL. |
|
|
isError() |
|
|
|
|
|
Проверка, является ли результат ошибкой. |
|
|
query($query, $params) |
|
|
|
Выполнение запроса к базе данных. |
|
||
|
|
|
|
|
|
|
string $query – SQL запрос; |
|
|
|
|
|
|
|
|
array $params – параметры запроса. |
|
|
queryLimit($query, |
|
|
|
Генерация ограниченного (лимитированного) запроса. |
|
||
|
|
$from, $count) |
|
|
|
int $from – номер строки, с которой начинать выбор; |
|
|
|
|
|
|
|
|
|
int $count – число возвращаемых записей. |
|
|
queryOne($query, $params) |
|
|
|
Получение значения 1-ой строки 1-ого столбца результата |
|
||
|
|
|
|
|
|
|
запроса. |
|
|
queryRow($query, $params) |
|
|
|
Получение значений 1-ой строки результата запроса. |
|
||
|
queryCol($query, $params) |
|
|
|
Получение значений 1-ого столбца результата запроса. |
|
||
|
queryAssoc($query, $params) |
|
|
|
Получение результатов запроса в виде ассоциативного |
|
||
|
|
|
|
|
|
|
массива, используя первый столбец в качестве ключей. |
|
|
|
|
|
4 |
|
Предопределённые константы.
Код состояния (константа) |
Описание |
|
|
DB_OK |
Ошибок нет |
DB_ERROR_SYNTAX |
Синтаксическая ошибка запроса к базе данных |
DB_ERROR_CONSTRAINT |
Отсутствует внешний ключ |
DB_ERROR_NOT_FOUND |
Попытка удалить несуществующий индекс |
DB_ERROR_ALREADY_EXISTS |
Попытка создания уже существующей таблицы |
DB_ERROR_UNSUPPORTED |
Запрошенная операция не поддерживается |
DB_ERROR_MISMATCH |
Число параметров запроса не совпадает с требуемым |
DB_ERROR_TRUNCATED |
Возвращаемые данные были получены не полностью |
DB_ERROR_INVALID |
Ошибка входных данных запроса к базе данных |
DB_ERROR_INVALID_DSN |
Неверно указаны данные соединения |
DB_ERROR_INVALID_NUMBER |
Попытка записи нечислового значения в числовое поле |
DB_ERROR_INVALID_DATE |
Неверный формат даты в запросе к базе данных |
DB_ERROR_DIVZERO |
Ошибка деления на ноль при запросе к базе данных |
DB_ERROR_NODBSELECTED |
Не указана база данных при попытке соединения |
DB_ERROR_CANNOT_CREATE |
Невозможно создать таблицу или файл базы данных |
DB_ERROR_CANNOT_DROP |
Невозможно удалить таблицу или файл базы данных |
DB_ERROR_NOSUCHTABLE |
Попытка обращения к несуществующей таблице |
DB_ERROR_NOSUCHFIELD |
Попытка обращения к несуществующему полю |
DB_ERROR_NOSUCHDB |
Попытка доступа к несуществующей базе данных |
DB_ERROR_NEED_MORE_DATA |
Необходимо больше данных |
DB_ERROR_CONNECT_FAILED |
Невозможно установить соединение с базой данных |
DB_ERROR_ACCESS_VIOLATION |
Ошибка доступа к таблице или файлу базы данных |
Установка соединения с базой данных.
Ниже приведены методы класса DB, выполняющие соединение и разъединение с базой данных. Для этих целей в методе используются функции PHP mysql_connect, mysql_error, mysql_select_db и mysql_close. В
качестве входного параметра метод установки соединения использует ассоциативный массив данных соединения (хост, порт, имя пользователя, пароль, название базы данных).
1 public function connect($dsn)
2{
3$this->dsn = $dsn;
5// Подготовка параметров подключения к базе данных
6$params = array();
7$params[0] = $dsn['host'] ? $dsn['host'] : 'localhost';
8if($dsn['port'])
9$params[0] .= ':' . $dsn['port'];
10$params[] = $dsn['username'] ? $dsn['username'] : null;
11$params[] = $dsn['password'] ? $dsn['password'] : null;
13// Попытка установки подключения
14$this->connection = @call_user_func_array('mysql_connect', $params);
5
15
16// Ошибка установки соединения
17if(!$this->connection)
18{
19if(($err = @mysql_error()) != '') {
20 |
return $this->Error(DB_ERROR_CONNECT_FAILED, $err); |
21 |
else |
22 |
return $this->Error(DB_ERROR_CONNECT_FAILED); |
23 |
} |
24 |
|
25// Выбор базы данных
26if($dsn['database'])
27{
28if(!@mysql_select_db($dsn['database'], $this->connection))
29 |
return $this->Error(DB_ERROR_NOSUCHDB); |
30 |
else |
31 |
return DB_OK; |
32}
33}
34
35public function disconnect()
36{
37$ret = @mysql_close($this->connection);
38$this->connection = null;
39return $ret;
40}
Выполнение SQL запросов.
Перед непосредственным выполнением запросов к базе данных, он должен быть специальным образом обработан для защиты от одного из самых распространённых способов взлома сайтов – SQL инъекций.
SQL инъекции являются попытками злоумышленников внедрить произвольный SQL код в запрос. Внедрение SQL, в зависимости от типа используемой СУБД и условий внедрения, может дать возможность атакующему выполнить произвольный запрос к базе данных (например, прочитать содержимое любых таблиц, удалить, изменить или добавить данные), получить возможность чтения и/или записи локальных файлов и выполнения произвольных команд на атакуемом сервере.
Атака типа внедрения SQL может быть возможна из-за некорректной обработки входных данных, используемых в SQL-запросах.
Допустим, серверное ПО, получив входной параметр, использует его для создания SQL-запроса. Рассмотрим следующий PHP скрипт:
1$id = $_REQUEST['id'];
2$res = mysql_query("SELECT * FROM news WHERE id_news = $id");
Если на сервер передан параметр, равный «5», то выполнится следующий SQL-запрос:
SELECT * FROM news WHERE id_news = 5
6
Но если злоумышленник передаст в качестве параметра строку «-1 OR 1=1», то выполнится запрос:
SELECT * FROM news WHERE id_news = -1 OR 1=1
Таким образом, изменение входных параметров путѐм добавления в них конструкций языка SQL вызывает изменение в логике выполнения SQL-запроса (в данном примере вместо новости с заданным идентификатором будут выбраны все имеющиеся в базе новости, поскольку выражение 1=1 всегда истинно).
Чтобы внедрение кода было невозможно, для некоторых СУБД, в том числе, для MySQL, требуется брать в кавычки все строковые параметры. В самом параметре заменяют кавычки на \", апостроф на \', обратную косую черту на \\ (экранировать спецсимволы). Реализацию данных операций реализуем встроенными средствами языка PHP и включим в класс DB:
1private function escape($str)
2{
3if(function_exists('mysql_real_escape_string'))
4return @mysql_real_escape_string($str, $this->connection);
5else
6return @mysql_escape_string($str);
7}
Далее приведём код ключевого метода query, а также вспомогательные (приватные) методы класса. Остальные методы выполнения запросов
(queryOne, queryAssoc, queryCol, queryLimit и пр.) базируются именно на методе query. Методу подаётся на вход запрос, в котором места подстановки конкретных значений параметров указываются символом «?», и массив значений подставляемых параметров. Все значения параметров будут соответствующим образом обработаны, подставлены в запрос и окружены кавычками.
1public function query($query, $params = array())
2{
3// Запрос с параметрами
4if(sizeof($params) > 0)
5{
6$sth = $this->escape($query);
7if(DB::isError($sth))
8 |
return $sth; |
9 |
|
10$ret = $this->execute($sth, $params);
11return $ret;
12}
13// Запрос без параметров (для ускорения выполнения)
14else
15{
16$this->last_parameters = array();
17$result = $this->simple($query);
18if($result === DB_OK || DB::isError($result))
19 |
return $result; |
20else
21{
7
22 |
$tmp = |
new DB_result($this, $result); |
23 |
return |
$tmp; |
24}
25}
26}
27 |
|
28 |
private function execute($stmt, $data = array()) |
29{
30$stmt = (int)$stmt;
31$data = (array)$data;
32$this->last_parameters = $data;
34if(count($this->prepare_types[$stmt]) != count($data))
35{
36$this->last_query = $this->prepared_queries[$stmt];
37return $this->raiseError(DB_ERROR_MISMATCH);
38}
39
40 $realquery = $this->prepare_tokens[$stmt][0]; 41
42// Обработка параметров запроса и построение запроса
43$i = 0;
44foreach ($data as $value)
45{
46if($this->prepare_types[$stmt][$i] == DB_PARAM_SCALAR)
47 |
$realquery .= $this->quote($value); |
48elseif ($this->prepare_types[$stmt][$i] == DB_PARAM_OPAQUE)
49{
50 |
$fp = @fopen($value, 'rb'); |
51 |
if(!$fp) |
52 |
{ |
53 |
return $this->raiseError(DB_ERROR_ACCESS_VIOLATION); |
54 |
} |
55 |
$realquery .= $this->quote(fread($fp, filesize($value))); |
56 |
fclose($fp); |
57}
58else
59 |
$realquery .= $value; |
60$realquery .= $this->prepare_tokens[$stmt][++$i];
61}
62
63return $realquery;
64}
65
66private function simple($query)
67{
68$this->last_query = $query;
70// Выполнение запроса без параметров
71if(!$this->options['result_buffering'])
72$result = @mysql_unbuffered_query($query, $this->connection);
73else
74$result = @mysql_query($query, $this->connection);
75
76return DB_OK;
77}
8
Пример использования.
1$dsn = array(
2'host' => 'prepod.mysql:3306',
3'database' => 'prepod_db',
4'username' => 'prepod_admin',
5'password' => 'hfsrwcnt'
6);
7
8 $db = new DB();
9
10// Установка соединения с базой данных
11$connect = $db->connect($dsn);
12if(DB::isError($connect))
13die('Ошибка подключения к базе данных');
15// Выполнение запроса
16$results = $db->queryAssoc('SELECT login, email FROM users WHERE id = ?',
17array($_REQUEST['id']));
18if(DB::isError($result))
19die('Ошибка выполнения запроса к базе данных');
21// Вывод результата
22foreach($result as $login => $email)
23echo $login . ' ' . $email . '<br />';
9