Разработка web - приложениия “КиноПоиск.Ру” на языке PHP
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ
НЕФТЕКАМСКИЙ ФИЛИАЛ
ФЕДЕРАЛЬНОГО ГОСУДАРСТВЕННОГО БЮДЖЕТНОГО ОБРАЗОВАТЕЛЬНОГО УЧРЕЖДЕНИЯ ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ
«БАШКИРСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ»
Экономико-математический факультет Кафедра математического моделирования и информационной безопасности |
КУРСОВАЯ работа
по дисциплине «Уравнения свертки»
на тему
«Разработка web - приложениия “КиноПоиск.Ру” на языке PHP»
|
|
Выполнил: студент 3 курса очной формы обучения группы М-31 Назмутдинов А.А.__________
Научный руководитель: к.ф.-м.н., доц. Вильданов А.Н.____________ |
Нефтекамск 2013
СОДЕРЖАНИЕ
ВВЕДЕНИЕ
Язык PHP был создан осенью 1994 года, программистом Расмусом Лердорфом. Лердорф собирался написать простой «движок» для своей персональной странички и завершил эту работу к началу 1995 года. Движок был написан на языке Perl и умел делать очень немного, так как создавался только для подсчета количества посетителей странички Расмуса. Этот движок был назван Personal Home Page Tools (PHPT), и единственной его возможностью был подсчет посетителей.
Стоит заметить, что в 1994 году никаких инструментов для создания различных приложений для Web еще не было, да и сам Web только еще начинался. Поэтому те задачи, которые решала программа Расмуса, были актуальны для очень многих пользователей сети, и к нему хлынул поток писем с просьбами предоставить свой инструментарий. К концу 1997 года два программиста Зив Сураски и Энди Гутманс переписали первоначальный лексический анализатор, и к лету 1998 года в полной мере увидела свет третья версия языка - PHP 3. Развитие PHP стремительно продолжалось, в язык сотнями добавлялись новые функции, и в 1999 году число разработчиков, использующих PHP, превысило 1 миллион, что сделало PHP одним из самых популярных языков для разработки Web - приложений. К этому времени к разработке языка подключилось большое количество программистов со всего мира.
На настоящий момент используется пятая версия языка PHP. Данный язык набирает все большую популярность, ведь его возможности практически не ограничены. Однако, еще большей его популяризации мешает тот факт, что далеко не все пользователи решившие создать свой сайт или страничку умеют программировать на достаточно высоком уровне. Именно эту проблему частично мы и попытаемся решить. Целью данной работы является создание киноафиши, на языке PHP с использованием СУБД MySQL для просмотра расписания фильмов.
Поставленная цель определила постановку следующих задач:
- изучение существующей организации киноафиши;
- изучение СУБД MySQL, ее установка, настройка, конфигурирование;
- изучение средств языка РНР для работы с СУБД MySQL;
- проектирование таблиц базы данных приложения;
- разработка динамических веб-страниц Киноафиши.
1 СУБД MySQL
Рассмотрим наиболее часто используемых функций, позволяющих работать с базой данных MySQL средствами РНР.
При взаимодействии РНР и MySQL программа взаимодействует с СУБД посредством совокупности функций.
1.1 Соединение с сервером. Функция mysql_connect
Прежде чем работать с базой данных, необходимо установить с ней сетевое соединение, а также провести авторизацию пользователя. Для этого служит функция mysql_connect()
resource mysql_connect([string $server[,string $username[,string $password]]])
Эта функция устанавливает сетевое соединение с базой данных MySQL, расположенной на хосте $server (по умолчанию это localhost, т.е. текущий компьютер) и возвращает идентификатор открытого соединения. Вся дальнейшая работа ведется именно с этим идентификатором. Все другие функции, принимающие этот идентификатор (дескриптор) в качестве аргумента, будут однозначно определять выбранную базу данных. При регистрации указывается имя пользователя $username и пароль $password (по умолчанию имя пользователя, от которого запущен текущий процесс – при отладке скриптов: root, и пустой пароль):
<?
$dblocation = "localhost"; //Имя сервера
$dbuser = "root"; //Имя пользователя
$dbpasswd = ""; //Пароль
//Осуществляем соединение с сервером базы данных
//Подавляем вывод ошибок
$dbcnx = @ mysql_connect($dblocation, $dbuser, $dbpasswd);
if (!$dbcnx) //Если дескриптор равен 0, соединение не установлено
{
//Выводим предупреждение
echo("<P>B настоящий момент сервер
базы данных не доступен, поэтому
корректное отображение
exit ();
}
?>
Переменные $dblocation, $dbuser и $dbpasswd хранят имя сервера, имя пользователя и пароль1.
1.2 Разрыв соединения с сервером. Функция mysql_close
Соединение с MySQL – сервером будет автоматически закрыто по завершении работы сценария, либо же при вызове функции mysql_close
bool mysql_close ([resource $link_identifier])
Эта функция разрывает соединение с сервером MySQL, и возвращает true при успешном выполнении операции и false в противном случае. Функция принимает в качестве аргумента дескриптор соединения с базой данных, возвращаемый функцией mysql_connect.
Пример работы с этой функцией:
<?
$dblocation = "localhost"; //Имя сервера
$dbuser = "root"; //Имя пользователя
$dbpasswd = ""; //Пароль
//Осуществляем соединение с сервером базы данных
//Подавляем вывод ошибок
$dbcnx = @ mysql_connect($dblocation, $dbuser, $dbpasswd);
if (!$dbcnx) //Если дескриптор равен 0, соединение не установлено
{
//Выводим предупреждение
echo("<P>B настоящий момент сервер
базы данных не доступен, поэтому
корректное отображение
exit ();
}
if (mysql_close($dbcnx)) //разрываем соединение
{
echo("Соединение с базой
}
else
{
echo("He удалось завершить соединение")
?>
1.3 Создание базы данных. Функция CREATE DATABASE
Команда – создание базы данных доступна только администратору сервера, и на большинстве хостингов ее нельзя выполнять:
CREATE DATABASE ИмяБазыДанных
Создает новую базу данных с именем имяБазыданных.
Пример работы с этой функцией:
//Создаем базу данных $dbname – это может делать только суперпользователь
//Если база данных уже
@mysql_query('CREATE DATABASE $dbname');
Рекомендуется везде использовать апострофы ('SQL – команда') в качестве ограничителей строк, содержащих SQL – команды. Этим можно гарантировать, что никакая $ - переменная случайно не будет интерполирована (т.е. не заменится на свое значение), и увеличится безопасность скриптов.
Команда создания базы данных CREATE DATABASE доступна только суперпользователю, и на большинстве хостингов простому пользователю ее выполнить невозможно. Она доступна только администратору сервера.
Для экспериментов создадим базу данных testbase, выполнив SQL-запрос из командной строки. Для этого нужно войти в систему MySQL и ввести в командной строке MySQL (рисунок 1):
mysql> create database testbase;
После этого следует набрать:
mysql>use testbase;
Рисунок 1– Создание базы данных
База данных создана видно (рисунок 2):
Рисунок 2 – Созданная база данных
1.4 Создание таблицы. Функция CREATE TABLE
CREATE [IF NOT EXISTS] TABLE Имя Таблицы (ИмяПоля тип, ИмяПоля тип,)
Этой командой в базе данных создается новая таблица с колонками (полями), определяемыми своими именами (ИмяПоля) и указанными типами. После создания таблицы в нее можно будет добавлять записи, состоящие из перечисленных в данной команде полей.
Листинг test_11.php. Программа, создающая новую таблицу в базе данных:
<?php ## Создание новой таблицы в БД.
include "config.php";//Подключение к серверу и выбор базы данных
mysql_query('CREATE TABLE if not exists people
(
id INT AUTO_INCREMENT PRIMARY KEY,
name TEXT)');
or die("MySQL error: ".mysql_error());
?>
Этот сценарий создает новую таблицу people с двумя полями. Первое поле имеет тип INT (целое) и имя id. Второе — тип TEXT (текстовая строка) и имя name.
Если таблица существует, сработает конструкция or die ().
Необязательная фраза if not exists, если она задана, говорит серверу MySQL, что он не должен генерировать сообщение об ошибке, если таблица с указанным именем уже существует в базе данных.
Необходимо сделать нужные изменения (изменить название базы данных на testbase) в файле config.php (рисунок 3):
Рисунок 3 – Листинг config.php
Таблица people создана (рисунок 4):
Рисунок 4 – Созданная таблица people
Можно просмотреть перечень таблиц созданной базы данных c помощью оператора SHOW (рисунок 5):
Рисунок 5 – Оператор SHOW
Можно отобразить информацию о столбцах всех таблиц c помощью оператора DESCRIBE (рисунок 6):
Рисунок 6 – Оператор DESCRIBE
Для просмотра данных, сохраненных в таблице, можно применить оператор SELEKT (рисунок 7):
Рисунок 7– Оператор SELEKT
Рекомендуется всегда создавать таблицы прямо в скриптах, которые с ними работают, потому что это делает сценарии автономными. К сожалению многие скрипты так не поступают. Обычно к ним прилагается SQL-файл с командами создания таблиц, который нужно запустить перед установкой скриптов. Этот способ не рекомендуется.
1.5 Вставка записей в таблицу. Функция INSERT
INSERT INTO ИмяТаблицы(ИмяПоля1 ИмяПоля2 ...) VALUES ('зн1', 'зн2',...)2.
Добавляет в таблицу ИмяТаблицы запись, у которой поля, обозначенные как ИмяПоля1 ИмяПоля2 установлены в значения соответственно зн№.
Те поля, которые в этой команде не перечислены, получают "неопределенные" значения.
Неопределенное значение (NULL) — это не пустая строка, а просто признак, который говорит MySQL, что у данного поля нет никакого значения3.
Впрочем, если для неуказанного здесь поля при создании таблицы был задан NOT NULL, то поле получит значение по умолчанию (чаще всего 0 или пустая строка). Значения полей можно заключать и в обычные кавычки, но апострофы тут использовать удобнее; к тому же, так положено по стандарту SQL. При вставке в таблицу бинарных данных (или текстовых, содержащих апострофы и слэши) некоторые символы должны быть "защищены" обратными слэшами, а именно символы \, ' и символ с нулевым кодом (в РНР обозначается как "\х00" или chr(0)).
Существует альтернативный синтаксис для данной команды, специфичный для MySQL:
INSERT INTO ИмяТаблицы SET ИмяПоля1='зн1', ИмяПоля2='зн2', . . .
На практике он часто оказывается удобнее первого.
1.6 Удаление записей. Функция DELETE
DELETE FROM ИмяТаблицы WHERE выражение
Удаляет из таблицы ИмяТаблицы все записи, для которых выполнено выражение. Параметр выражение — это просто логическое выражение, составленное "почти" по правилам РНР. Вот показательный пример:
DELETE FROM topics WHERE forum_id=10 AND user != "moderator"
В выражении, помимо имен полей, констант и операторов, могут также встречаться простейшие "вычисляемые" части, например: (id < 10+11*234).
Вообще говоря, формат выражения един для всех команд запросов, которые мы встретим в дальнейшем. Например, он же используется и в операции SELECN, и в операции UPDATE.
1.7 Обновление записей. Функция UPDATE
UPDATE ИмяТаблицы SET (ИмяПоля1= 'зн1', ИмяПоля1— 'зн2', ...) WHERE выражение
В таблице ИмяТаблицы для всех записей, удовлетворяющих выражению выражение, указанные поля устанавливаются в соответствующие значения. При этом остальные поля остаются без изменения. Эта команда часто выполняется, если не требуется обновлять сразу все поля какой-то записи, а нужно затронуть только некоторые.
1. Отправка запроса серверу для извлечения одной стоки из таблицы базы данных. Функция mysql_query
resource mysql_query (string query)
Эта функция применяется для отправки серверу SQL-запросов. Функция возвращает дескриптор запроса в случае успеха и false — в случае неудачного выполнения запроса.
В листинге показан код, с помощью которого извлекается одна строка из таблицы customers базы данных books:
<?
include "config.php";//Подключение к серверу и выбор базы данныхх
$ath = mysql_query("select * from customers;");
if($ath)
{
$author = mysql_fetch_array($ath);
echo "<br>имя = ".$author['name']."<br>";
echo "адрес = ".$author['city']."<br>";
}
else
{
echo "<p><b>Error: ".mysql_error () . "</b></p>" ;
exit () ;
}
?>
Результат выполнения запроса для вывода одной строки из таблицы (рисунок 8):
Рисунок 8 – Вывод запроса вывода строки
2. Вывод всех строк таблицы базы данных в виде ассоциативного массива. Функция mysql_fetch_array
array mysql_fetch_array (resource result)
Эта функция возвращает значения полей в виде ассоциативного массива. В качестве аргумента принимает дескриптор запроса, возвращаемый функцией mysql_query.
В листинге показано, как с помощью этой функции можно вывести все строки таблицы customers:базы данных books
<?
include "config.php";//Подключение к серверу и выбор базы данных
$ath = mysql_query("select * from customers;");
if($ath)
{
//Определяем таблицу и
echo "<table border=1>";
echo"<tr>
<td>имя</td>
<td>адрес</td>
</tr>";
//Так как запрос возвращает несколько строк, применяем цикл
while($author = mysql_fetch_array($ath))
{
echo "<tr>
<td>".$author['name']." <
<td>".$author['city']."   </td>
</tr>";
}
echo "</table>";
}
else
{
echo "<p><b>Error: " .mysql_error () . "</b><p>";
exit () ;
}
?>
Результат выполнения запроса для вывода всех строк из таблицы (рисунок 9):
Рисунок 9 – Вывод запроса для вывода всех строк
3. Доступ к отдельному полю записи. Функция mysql_result
mixed mysql_result (resource result, int row)
С помощью этой функции можно получить доступ к отдельному полю записи. Допустим, нам нужно вывести имя автора, которое первым найдется в базе данных. Сделать это можно следующим образом:
<?
include "config.php";//Подключение к серверу и выбор базы данных
$ath = mysql_query("select name from customers;");
if($ath)
{
echo mysql_result($ath,0,'name');
}
else
{
echo "<p><b>Error: " .mysql_error () . "</b><p>";
exit () ;
}
?>
Результат выполнения запроса для вывода одной записи из таблицы (рисунок 10):
Рисунок 10 – Вывод запроса для одной записи
4. Возвращение поля записи в виде объекта. Функция mysql_fetch_object
object mysql_fetch_object (resource result)
Эта функция возвращает поля записи данных в виде объекта.
В листинге приведен пример, в котором с помощью этой функции из таблицы customers выводятся имя, и адрес авторов:
<?
include "config.php";//Подключение к серверу и выбор базы данных
$ath = mysql_query("select * from customers;");
if($ath)
{
while($row = mysql_fetch_object($ath))
{
echo "<p>имя: ".$row->name."</p>";
echo "<p>адрес: ".$row-> city."</p>";
}
}
else
{
echo "<p><b>Error: ".mysql_error () . "</b><p>";
exit();
}
?>
Результат выполнения скрипта (рисунок 11):
Рисунок 11 – Вывод скрипта
5. Возвращение массива, в котором содержится значение поля. Функция mysql_fetch_row
array mysql_fetch_row (resource result)
В отличие от функции mysql_fetch_object, эта функция возвращает не объект, а массив, в котором содержатся значения полей:
<?
include "config.php";//Подключение к серверу и выбор базы данных
$ath = mysql_query("select * from customers;");
if($ath)
{
while($row = mysql_fetch_row($ath))
{
echo "<p>имя: ".$row[3]."</p>";
echo "<p>адрес: ".$row[2]."</p>";
}
}
else
{
echo "<p><b>Error: " .mysql_error () . "</b><p>";
exit ();
}
?>
1.8 MySQL и проблемы безопасности
Запросы, отправляемые серверу MySQL, представляют собой обыкновенные строки РНР:
mysql_query("INSERT INTO table SET name='$name'");
В $name может храниться строка, содержащая апострофы.
Рассмотрим, какой запрос придет серверу MySQL, если $name равно "cat's":
INSERT INTO table SET name='cat's'4.
Эта команда синтаксически некорректна и породит ошибку во время выполнения.
Но может быть и хуже.
Рассмотрим такой запрос:
mysql_query("DELETE FROM table WHERE name='$name'");
Если параметр $name приходит из формы, и злоумышленник указал в нем следующую строку: "!' or 1=1 or '!", то после подстановки получится такой запрос к базе данных:
DELETE FROM table- WHERE name=' !' OR 1=1 OR ' !'
Этот запрос удалит все записи из таблицы table, потому что выражение SQL 1=1 всегда истинно.
Рассмотрим два способы защиты от подобных ошибок или действий злоумышленника:
- Экранирование спецсимволов.
- Шаблоны запросов и placeholders.
1.9. Экранирование спецсимволов
Прежде чем передавать значения переменных формы в SQL-запросы, необходимо специальным образом экранировать в них некоторые символы (в частности, апостроф), например, поставить перед ними обратный слэш. Для вставки предназначена функция:
mysql_escape_string()
string mysql_escape_string(string $str)
Функция похожа на другую функцию addslashes(), однако она добавляет слэши перед более полным набором специальных символов. Практика показывает, что для текстовых данных можно применять и функцию addslashes() вместо mysql_escape_string(). Во многих скриптах так и делается.
По стандарту MySQL экранированию подвергаются символы, которые в РНР записываются так: "\х00", "\n", "\г", "\\", ""', "" и "\х1А"5.
В это число входит символ с нулевым ASCII-кодом, а поэтому mysql_escape_string() допустимо применять не только для текстовых, но также и для бинарных данных. Можно, например, считать в переменную GIF-изображение (функция file_get_contents ()), а затем вставить его в базу данных, предварительно проэкранировав все спецсимволы. При извлечении картинка окажется в том же виде, в котором она была изначально.
Экранирование символов это лишь способ записи корректных SQL-выражений, не более того. С данными ничего не происходит, и они хранятся в базе без дополнительных слэшей — так, как выглядели изначально, еще до экранирования.
С использованием mysql_escape_string()код предыдущего запроса выглядит так:
mysql_query(
"DELETE FROM table WHERE name='".mysql_escape_string($
Это длинно, неуклюже и некрасиво.
1.10 Шаблоны запросов и placeholders
Рассмотрим другое решение.
Вместо явного экранирования и вставки переменных в запрос на их место помещают специальные маркеры (placeholders, "хранители места"), обычно выглядящие как ?.
Те же значения, которые будут подставлены вместо них, передаются отдельно, дополнительными параметрами.
С использованием гипотетической функции mysql_qwo, код которой будет представлен ниже, предыдущий запрос может быть переписан так:
mysql_qw ('DELETE FROM table WHERE name=?', $name)6;
Запрос стал короче и лучше защищен: теперь мы уже при написании кода не сможем случайно пропустить вызов функции mysql_escape_string() и, таким образом, попасться на уловку хакера. Все преобразования происходят автоматически, внутри функции.
В листинге lib_mysql_qw.php содержится простейшая реализация функции mysql_qw() (qw — от англ. query wrapper, "обертка для запроса").
В большинстве ситуаций возможностей, предоставляемых функцией mysql_qw (), оказывается достаточно.
Листинг lib_mysql_qw.php
<?php ## Простейшая функция для работы с placeholders.
// result-set, mysql_qw ($connection_id, $query, $argl, $arg2 ...).
// - или -
// result-set mysql_qw($query, $argl, $arg2, ...)
// Функция выполняет запрос к MySQL через соединение, заданное как
// $connection_id (если не указано, то через последнее открытое).
// Параметр $query может содержать подстановочные знаки ?,
// вместо которых будут
// аргументов $arg1, $arg2 и т. д. (по порядку), экранированные и
// заключенные в апострофы.
function mysql_qw()
{
// Получаем все аргументы
$args = func_get_args();
// Если первый параметр имеет тип "ресурс", то это ID-соединения.
$соnn = null;
if (is_resource($args[0])) $conn = array_shift($args);
// Формируем запрос по шаблону.
$query = call_user_func_array("mysql_
// Вызываем SQL-функцию.
return $conn!==null ? mysql_query($query, $conn): mysql_query($query);
}
// string mysql_make_qw($query, $argl, $arg2,...)
// Данная функция формирует SQL-запрос по шаблону $query,
// содержащему placeholders.
function mysql_make_qw()
{
$args = func_get_args();
// Получаем в $tmp1 ССЫЛКУ на шаблон запроса.
$tmp1 =& $args[0];
$tmp1 - str_replace("%", "%%", $tmp1);
$tmp1 = str_replace("?", "%s", $tmp1);
// После этого $args[0] также окажется измененным.
// Теперь экранируем все
foreach ($args as $i=>$v)
{
if (!$i) continue; // это шаблон
if (is_int($v)) continue; // целые числа не нужно экранировать
$args[$i] = "'".mysql_escape_string($v)."'
}
//На всякий случай заполняем
20 последних аргументов
// значениями, чтобы в случае, если число "?" превышает количество
// параметров, выдавалась ошибка SQL-запроса (поможет при отладке).
for ($i=$c=count($args)-1; $i<$c+20; $i++)
$args[$i+1] = "UNKNOWN_PLACEHOLDER_$i";
// Формируем SQL-запрос.
return call_user_func_array("sprintf"
}
?>
Если убрать поясняющие записи, то размер файла lib_mysql_qw.php уменьшится почти в три раза:
<?php ## Простейшая функция для работы с placeholders.
function mysql_qw()
{
$args = func_get_args();
$соnn = null;
if (is_resource($args[0])) $conn = array_shift($args);
$query = call_user_func_array("mysql_
return $conn!==null ? mysql_query($query, $conn): mysql_query($query);
}
function mysql_make_qw()
{
$args = func_get_args();
$tmp1 =& $args[0];
$tmp1 - str_replace("%", "%%", $tmp1);
$tmp1 = str_replace("?", "%s", $tmp1);
foreach ($args as $i=>$v)
{
if (!$i) continue;
if (is_int($v)) continue;
$args[$i] = "'".mysql_escape_string($v)."'
}
for ($i=$c=count($args)-1; $i<$c+20; $i++)
$args[$i+1] = "UNKNOWN_PLACEHOLDER_$i";
return call_user_func_array("sprintf"
}
?>
Функция sprintf() воспринимает символ % как управляющий. Чтобы отменить его специальное действие, необходимо его удвоить, что и делается в функции. Затем ? заменяется на %s, для sprintf() это означает "взять очередной строковый аргумент"7.
Для удобства тестирования этого кода главная функция разбита на две, выделен код замены подстановочных знаков в функцию mysql_make_qw().
В листинге test_qw.php приведен пример того, как будут выглядеть SQL-запросы после подстановки placeholders.