Обработка запросов к БД при помощи PEARXML PHP


Оглавление (нажмите, чтобы открыть):

Работа с XML в PHP

Парсинг сайтов

Сейчас мы с вами изучим работу с XML. XML — это формат для обмена данными между сайтами. Он очень похож на HTML, только в XML разрешены свои теги и атрибуты.

Зачем нужен XML при парсинге? Иногда бывает так, что сайт, который вам нужно спарсить, имеет API, с помощью которого можно получить желаемое, особо не напрягаясь. Поэтому сразу совет — перед тем, как парсить сайт, проверьте, нету ли у него API.

Что такое API? Это набор функций, с помощью которых вы можете слать запрос этому сайту и получать нужный ответ. Вот этот ответ чаще всего приходит в формате XML. Поэтому давайте приступим к его изучению.

Работа с XML в PHP

Пусть у вас есть XML. Он может быть в строке, либо хранится в файле или отдаваться по запросу к определенному URL.

Пусть XML хранится в строке. В этом случае из этой строки нужно создать объект с помощью new SimpleXMLElement:

Сейчас у нас в переменной $xml хранится объект с разобранным XML. Обращаясь к свойствам этого объекта можно получать доступ с содержимому тегов XML. Как именно — разберем чуть ниже.

Если же XML хранится в файле или отдается по обращению к URL (что чаще всего и бывает), то следует использовать функцию simplexml_load_file, которая делает тот же объект $xml:

Приемы работы

В примерах ниже наш XML хранится в файле или по URL.

Пусть дан следующий XML:

Давайте получим имя, возраст и зарплату работника:

Как вы видите, у объекта $xml есть свойства, соответствующие тегам.

Вы может обратили внимание, что тег нигде не фигурирует при обращении. Это потому, что он корневой тег. Можно переименовать его, например, на — и ничего не поменяется:

Корневой тег в XML может быть только один, так же, как и тег в обычном HTML.

Давайте чуть модифицируем наш XML:

В этом случае у нас получится цепочка обращений:

Работа с атрибутами

Пусть некоторые данные хранятся в атрибутах:

Теги с дефисами

В XML разрешены теги (и атрибуты) с дефисом. В этом случае обращение к таким тегам происходит так:

Перебор циклом

Пусть теперь у нас не один работник, а несколько. В этом случае мы можем перебрать наш объект с помощью цикла foreach:

Из объекта в нормальный массив

Если вам неудобно работать с объектом, вы можете преобразовать его в нормальный массив PHP с помощью следующего хитрого приема:

Больше информации

Парсинг на основе sitemap.xml

Зачастую на сайте есть файл sitemap.xml. В этом файле хранятся ссылки на все страницы сайта для удобства индексации их поисковыми системами (индексация — это по сути и есть парсинг сайта яндексом и гуглом).

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

Как проверить наличие этого файла: пусть мы парсим сайт site.ru, тогда обратитесь в браузере к site.ru/sitemap.xml — если что-то увидите, значит он там есть, а если не увидите — то увы.

Если sitemap есть — то в нем содежатся ссылки на все страницы сайта в формате XML. Спокойно забираете этот XML, парсите его, отделяете ссылки на нужные вам страницы любым удобным вам способом (например, анализом URL, который был описан в методе паука).

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

Подробнее об устройстве sitemap.xml читайте в википедии.

Что вам делать дальше:

Приступайте к решению задач по следующей ссылке: задачи к уроку.

Когда все решите — переходите к изучению новой темы.

Работа с XML в PHP

Здравствуйте, уважаемые читатели блога LifeExample, в этой статье «Работа с XML в PHP» я расскажу о том, как считывать, перезаписывать, удалять и производить php запись в xml файл. А так же о том, как в принципе быстро и удобно создать и поместить данные в xml разметку. Будучи студентом работая над своими проектами, я самостоятельно писал библиотеки для обработки XML документов. Я очень рад, что теперь мне не приходится пользоваться своими велосипедами т.к. есть готовые решения присутствующие в PHP по умолчанию.

Работа с XML в PHP — PHP запись в XML

Инструмент XMLWriter был создан специально для записи в XML формате. Один из важных его методов это startDocument(), который позволяет задать кодировку версии XML.

Попробуем создать простенький XML следующего вида:

Получить такой формат можно с помощью XMLWriter таки вот образом:

Как видите, Работа с XML в PHP, благодаря XMLWriter становится невероятно простой, и сильно облегчает задачи записи XML формата. Далее приведу маленький комплекс примеров о том, как осуществить, на php запись в xml. Например, задача поставлена — получить файл XML в следующем формате:

1 / id>
2013-04-19 10:56:03 / time>
$350 / total>
/ customer>

2 / id>
2013-04-23 13:43:41 / time>
$1456 / total>
/ customer>
/ purchase>

Чтобы получить такую структуру нужно выполнить ряд не хитрых методов класса XMLWriter.

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

$1.00 / price>
3% / discount>
/ product>

$0.90 / price>
3% / discount>
/ product>
/ products>

С помощью XMLWriter, делается это так:

Работа с XML в PHP — Чтение и получение данных из XML

Ниже будет приведен пример чтения и получения данных из XML с использованием классов XMLReader и SimpleXMLElement. Читать будем уже имеющийся XML объект, который мы создали в примере №1 при PHP записи в XML.

XMLReader используется для получения заданного узла из XML.

// Чтение XML формата
$rxml = new XMLReader ( ) ; //Создание элемента для чтения
$rxml -> xml ( $nXML ) ; //Загрузка XML, $nXML — строка в формате XML

//Переместиться к первому элементу customer
while ( $rxml -> read ( ) && $rxml -> name !== ‘customer’ ) ;

//Получим значение поля total у второго узла дерева
while ( $rxml -> name === ‘customer’ ) <
//Чтение текущего дочернего через SimpleXMLElement
$node = new SimpleXMLElement ( $rxml -> readOuterXML ( ) ) ;
//Проверяем, номер элемента, если он равен 2 то это искомый элемент
if ( $node -> id == 2 ) <
$amountSpent = $node -> total ;
break ;
>
//Переместиться к следующему элементу customer
$rxml -> next ( ‘customer’ ) ;
>

Часто задача возникает в получении данных из XML по значению, какого либо атрибута. Давайте по примеру №2 из раздела PHP запись в XML, получим название, цену и скидку продукта по его атрибуту p >

$rxml = new XMLReader ( ) ;
$rxml -> xml ( $nXML2 ) ;
while ( $rxml -> read ( ) && $rxml -> name !== ‘product’ ) ; //Перемещаемся к первому продукту

$name = «» ;
$price = «» ;
$discount = «» ;
while ( $rxml -> name === ‘product’ ) <
if ( $rxml -> getAttribute ( «pid» ) == «315» ) //если p >
<
$node = new SimpleXMLElement ( $rxml -> readOuterXML ( ) ) ; //читаем значение элементов
$name = $node -> name ;
$price = $node -> price ;
$discount = $node -> discount ;
break ;
>
$rxml -> next ( ‘product’ ) ; //перемещаемся к следующему
>
echo «Продукт №315. Наименование: <$name>, цена: <$price>скидка: <$discount>» ;

Работа с XML в PHP — Добавление узлов дерева в существующий XML

Работая с XML в PHP, не редко приходится ломать голову над тем как добавить новый элемент в имеющуюся XML структуру. Используя XMLWriter и SimpleXMLElement сделать это очень легко:

Работа с XML в PHP — Перезапись элементов существующего XML

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

/**
* Перезапись узлов дерева XML формата.
*/

$productId = 314 ;
$parent = new DomDocument ;
// создаем новый элемент дома product
$parent_node = $parent -> createElement ( ‘product’ ) ;

//Добавляем атрибут
$attribute = $parent -> createAttribute ( «pid» ) ;
//устанавливаем значение
$attribute -> value = $productId ;
$parent_node -> appendChild ( $attribute ) ;

// Добавляем дочерний элементы
$parent_node -> appendChild ( $parent -> createElement ( ‘name’ , «Яблоко» ) ) ;
$parent_node -> appendChild ( $parent -> createElement ( ‘price’ , » $2 .00″ ) ) ;
$parent_node -> appendChild ( $parent -> createElement ( ‘discount’ , «1%» ) ) ;

//Вставляем созданные элементы в создаваемый ‘product’
$parent -> appendChild ( $parent_node ) ;

// Загружаем оригинальный XML формат
$dom = new DomDocument ;
$dom -> loadXML ( $nXML ) ;

// Находим имеющийся элемент с p >
$xpath = new DOMXpath ( $dom ) ;
$nodelist = $xpath -> query ( «/products/product[@p > <$productId>]» ) ;

$oldnode = $nodelist -> item ( 0 ) ;

// Импортируем созданый ранее элемент в текущее дерево
$newnode = $dom -> importNode ( $parent -> documentElement , true ) ;

// заменяем страрый элемент на новый
$oldnode -> parentNode -> replaceChild ( $newnode , $oldnode ) ;
// сохраняем XML
echo $dom -> saveXML ( ) ;

Работа с XML в PHP — Удаление элементов XML

Из всего выше рассмотренного, осталась только одна операция, без которой данную статью о работе с XML в PHP , нельзя считать завершенной – это удаление элементов. Удаление элементов самое легкое из всей связки операций. Ну что же, ломать – не стоить, давайте удалим один из продуктов.

//Удаление продукта Манго
//загрузим оригинальный формат XML
$productId = 315 ;
$dom = new DomDocument ;
$dom -> loadXML ( $nXML2 ) ;

// Найдем элемент который необходимо удалить
$xpath = new DOMXpath ( $dom ) ;
$nodelist = $xpath -> query ( «/products/product[@p > <$productId>]» ) ;
$oldnode = $nodelist -> item ( 0 ) ;
// Удаляем элемент
$oldnode -> parentNode -> removeChild ( $oldnode ) ;
echo $dom -> saveXML ( ) ;

Закрыть текущий элемент (тэг) в xmlwriter

Найдя время и отвлекшись от основного своего проекта, я всё-таки опубликовал действительно полезную статью «Работа с XML в PHP«, и надеюсь она пригодится в своих разработках. Пишите мне на e-mail, с какими задачами вы сталкиваетесь, и я попробую сформировать материал по их решению в следующих статьях

Примеры использования PDO MySQL

Ниже приведены основные примеры работы с расширением PHP PDO. Такие как подключение к БД, получение, изменение и удаление данных. Подробнее о методах PDO можно узнать на php.net.

Для примеров используется таблица `category` с полями `id` , `name` и `parent` .

Подключение к серверу MySQL

Четвертым параметром конструктора PDO можно указать параметры подключения, например SQL запрос который будет выполнен сразу после подключения:

Чтобы отследить ошибку подключения к БД используется исключение:

Выборка из БД

Выборка одной записи

PDO позволяет использовать в запросах псевдопеременные чтобы исключить SQL инъекции. В самом запросе в место данных указывается ? или :id , а в методе execute() указываются реальные значения этих переменных.

Выборка всех записей таблицы

Данный пример получает всю таблицу в виде ассоциативного массива:

Получить значение поля одной записи

Получение всех значений одного столбца таблицы

Пример получает все значения поля `name` из таблицы `category` .

Обработка запросов к БД при помощи PEAR::XML PHP

За выполнение запросов отвечают функции mysqli_query() , mysqli_real_query() и mysqli_multi_query() . Чаще всего применяется функция mysqli_query() , так как она выполняет сразу две задачи: выполняет запрос и буферизует на клиенте результат этого запроса (если он есть). Вызов mysqli_query() идентичен последовательному вызову функций mysqli_real_query() и mysqli_store_result() .

Пример #1 Подключение к MySQL

= new mysqli ( «example.com» , «user» , «password» , «database» );
if ( $mysqli -> connect_errno ) <
echo «Не удалось подключиться к MySQL: (» . $mysqli -> connect_errno . «) » . $mysqli -> connect_error ;
>

if (! $mysqli -> query ( «DROP TABLE IF EXISTS test» ) ||
! $mysqli -> query ( «CREATE TABLE test(id INT)» ) ||
! $mysqli -> query ( «INSERT INTO test(id) VALUES (1)» )) <
echo «Не удалось создать таблицу: (» . $mysqli -> errno . «) » . $mysqli -> error ;
>
?>

Буферизация результатов запроса

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

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

Пример #2 Навигация по строкам буферизованной результирующей таблицы


= new mysqli ( «example.com» , «user» , «password» , «database» );
if ( $mysqli -> connect_errno ) <
echo «Не удалось подключиться к MySQL: (» . $mysqli -> connect_errno . «) » . $mysqli -> connect_error ;
>

if (! $mysqli -> query ( «DROP TABLE IF EXISTS test» ) ||
! $mysqli -> query ( «CREATE TABLE test(id INT)» ) ||
! $mysqli -> query ( «INSERT INTO test(id) VALUES (1), (2), (3)» )) <
echo «Не удалось создать таблицу: (» . $mysqli -> errno . «) » . $mysqli -> error ;
>

$res = $mysqli -> query ( «SELECT id FROM test ORDER BY id ASC» );

echo «Обратный порядок. \n» ;
for ( $row_no = $res -> num_rows — 1 ; $row_no >= 0 ; $row_no —) <
$res -> data_seek ( $row_no );
$row = $res -> fetch_assoc ();
echo » > . $row [ ‘id’ ] . «\n» ;
>

echo «Исходный порядок строк. \n» ;
$res -> data_seek ( 0 );
while ( $row = $res -> fetch_assoc ()) <
echo » > . $row [ ‘id’ ] . «\n» ;
>
?>

Результат выполнения данного примера:

Небуферизуемые результирующие наборы

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

Пример #3 Навигация по строкам небуферизованной результирующей таблицы

-> real_query ( «SELECT id FROM test ORDER BY id ASC» );
$res = $mysqli -> use_result ();

echo «Порядок строк в результирующем наборе. \n» ;
while ( $row = $res -> fetch_assoc ()) <
echo » > . $row [ ‘id’ ] . «\n» ;
>
?>

Типы данных значений в результирующей таблице

Функции mysqli_query() , mysqli_real_query() и mysqli_multi_query() предназначены для выполнения неподготавливаемых запросов. На уровне протокола клиент-серверного взаимодействия MySQL за выполнение запросов отвечают команда COM_QUERY и текстовый протокол. Когда используется текстовый протокол, сервер MySQL перед отправкой клиенту преобразует все данные в результирующем наборе в текстовые строки. Это преобразование выполняется вне зависимости от типа данных SQL-столбца результирующей таблицы. Клиентские библиотеки mysql, в свою очередь, получают все данные, принимая их за строки. На клиенте не проводится никакого обратного преобразования к исходным типам, все данные, полученные приложением остаются PHP строками.

Пример #4 Текстовый протокол по умолчанию возвращает строки

= new mysqli ( «example.com» , «user» , «password» , «database» );
if ( $mysqli -> connect_errno ) <
echo «Не удалось подключиться к MySQL: (» . $mysqli -> connect_errno . «) » . $mysqli -> connect_error ;
>

if (! $mysqli -> query ( «DROP TABLE IF EXISTS test» ) ||
! $mysqli -> query ( «CREATE TABLE test(id INT, label CHAR(1))» ) ||
! $mysqli -> query ( «INSERT INTO test(id, label) VALUES (1, ‘a’)» )) <
echo «Не удалось создать таблицу: (» . $mysqli -> errno . «) » . $mysqli -> error ;
>

$res = $mysqli -> query ( «SELECT > );
$row = $res -> fetch_assoc ();

printf ( » > , $row [ ‘id’ ], gettype ( $row [ ‘id’ ]));
printf ( «label = %s (%s)\n» , $row [ ‘label’ ], gettype ( $row [ ‘label’ ]));
?>

Результат выполнения данного примера:

Если используется библиотека mysqlnd, можно включить преобразование целочисленных значений и чисел с плавающей запятой из столбцов таблицы в PHP числа. Делается это заданием настройки подключения MYSQLI_OPT_INT_AND_FLOAT_NATIVE . В таком случае mysqlnd будет проверять метаданные столбцов и преобразовывать SQL-числа этих полей в PHP-числа, если эти значения не выходят за рамки допустимых диапазонов типов данных PHP. То есть, например, SQL INT число попадет в PHP приложение в виде целого (integer).

Мастер Йода рекомендует:  Приложение Facebook Home стало доступно для загрузки

Пример #5 Получение исходных типов данных в приложении

= mysqli_init ();
$mysqli -> options ( MYSQLI_OPT_INT_AND_FLOAT_NATIVE , 1 );
$mysqli -> real_connect ( «example.com» , «user» , «password» , «database» );

if ( $mysqli -> connect_errno ) <
echo «Не удалось подключиться к MySQL: (» . $mysqli -> connect_errno . «) » . $mysqli -> connect_error ;
>

if (! $mysqli -> query ( «DROP TABLE IF EXISTS test» ) ||
! $mysqli -> query ( «CREATE TABLE test(id INT, label CHAR(1))» ) ||
! $mysqli -> query ( «INSERT INTO test(id, label) VALUES (1, ‘a’)» )) <
echo «Не удалось создать таблицу: (» . $mysqli -> errno . «) » . $mysqli -> error ;
>

$res = $mysqli -> query ( «SELECT > );
$row = $res -> fetch_assoc ();

printf ( » > , $row [ ‘id’ ], gettype ( $row [ ‘id’ ]));
printf ( «label = %s (%s)\n» , $row [ ‘label’ ], gettype ( $row [ ‘label’ ]));
?>

Пакетная обработка данных в PHP

Как создавать долгосрочные задачи

Крупные сети продовольственных магазинов сталкиваются с большими проблемами. Когда люди покупают продукты, в каждом магазине ежедневно совершаются тысячи транзакций. Управляющим необходимо обрабатывать имеющиеся данные. Какие товары пользуются спросом? Какие нет? Где больше спрос на товары органического происхождения? Как обстоит дело с мороженым?

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

Ваше Web-приложение может обрабатывать не такие большие объемы данных, но на любом сайте могут быть процессы, требующие больше времени для выполнения, чем согласен ждать клиент. Общепринятое время, в течение которого пользователь может ждать, прежде чем процесс покажется ему «медленным», составляет 200 миллисекунд. Эта цифра основана на работе настольных приложений, и я думаю, что Web приучил нас быть более терпеливыми. Тем не менее, вам едва ли захочется заставлять клиента ждать дольше нескольких секунд. Итак, в данной публикации приведено несколько стратегий для пакетной обработки данных в PHP.

Проза жизни и cron

Центральным игроком в пакетной обработке данных для машин под UNIX® является демон cron . Этот демон считывает файл конфигурации, который сообщает ему, какие командные строки выполнять, и как часто. Затем демон выполняет их, работая как часовой механизм. Он даже отправляет любые сообщения об ошибках по указанному e-mail адресу, так что вы можете устранять ошибки при их возникновении.

Я знаю, что инженеры, отстаивающие преимущества конкурирующей Web-технологии, чье название ассоциируется с кофе, качают сейчас головами. «Потоки! Потоки — вот верный способ выполнять обработку в пакетном режиме. Демон cron — это динозавр.»

Я позволю себе с ними не согласиться.

Я работал и с тем, и с другим, и думаю, что cron имеет то преимущество, что в нём соблюдается принцип «Keep It Simple, Stupid» (KISS) — будь проще, дурачок. Он позволяет сохранить фоновую обработку простой. Вместо приложения с многопоточной обработкой задания, выполняемого бесконечно долго и никогда не освобождающего ресурсы памяти, вы имеете простой скрипт, который запускает cron . Скрипт определяет, есть ли работа, которая должна быть выполнена, выполняет ее, а затем его выполнение завершается. Не нужно волноваться об утечках памяти. Не нужно переживать, что поток остановится или попадет в ловушку бесконечного цикла.

Итак, как работает cron ? Это зависит от вашего хостинг-решения. Я буду придерживаться старой доброй UNIX-версии cron с командной строкой, а вы можете проконсультироваться с вашим системным администратором, как можно реализовать её в вашем Web-приложении.

Ниже приведена простая настройка cron для выполнения PHP-скрипта раз в день в 11 часов вечера:

Первые пять полей определяют время запуска скрипта. Затем идет имя пользователя, которое должно использоваться при запуске программы. Оставшаяся часть строки — командная строка для выполнения. В поле времени задаются минута, час, день месяца, месяц и день недели. Ниже приведено несколько примеров.

запускает скрипт по отметке 15 минут каждый час.

запускает скрипт по отметке 15 и 45 минут каждый час.

запускает скрипт каждую минуту с 3 ч. утра до 11 ч. вечера.

запускает скрипт в 11:30 вечера по субботам (день недели задан цифрой 6 ).

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

Используйте директиву MAILTO , чтобы указать, куда должны отправляться сообщения об ошибках в виде e-mail:

Примечание: Для пользователей Microsoft® Windows® существует аналогичная система «Назначенные задания» для запуска выполнения процессов из командной строки (как PHP-скрипт) через заданные промежутки времени.

Основы архитектуры пакетной обработки данных

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

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

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

Очередь сообщений

Первым вариантом является специализированная система очередей сообщений. В данной модели БД содержит таблицу со списком сообщений e-mail, которые должны быть разосланы разным людям. В Web-интерфейсе для добавления e-mail в очередь используется класс mailouts . Программа обработки e-mail использует класс mailouts для выборки ждущих обработки сообщений и их последующего удаления из очереди.

Модель начинается схемой MySQL.

Листинг 1. mailout.sql

Эта схема достаточно проста. Каждая строка содержит адреса from (откуда) и to (куда) , а также тему и содержание e-mail.

Оболочкой таблицы mailouts в БД служит класс PHP mailouts .

Листинг 2. mailouts.php

В скрипте использован класс доступа к БД Pear::DB. Затем он определяет класс mailouts с тремя основными статическими функциями: add) , delete и get_all . Метод add() предназначен для добавления почтового сообщения в очередь и должен использоваться пользователем внешнего интерфейса. Метод get_all() возвращает все данные из таблицы. Метод delete() удаляет отдельный метод.

Вы, возможно, спросите, почему бы не ввести метод delete_all() — «удалить все», который вызывался бы в конце работы программы. Такого метода не существует по двум причинам: если я удаляю каждое сообщение после отправки, то исключаю возможность повторного отправления сообщения в случае перезапуска скрипта при возникновении неполадок; и, кроме того, между началом и завершением пакетного задания могут быть добавлены новые сообщения.

Следующим этапом является написание простой тестового скрипта для добавления записи в очередь.

Листинг 3. mailout_test_add.php

В данном случае я добавляю mailout и пишу Молли из какой-то компании (по адресу molly@nocompany.com.org), а также тему и содержание письма e-mail. Я могу запустить эту программу из командной строки: php mailout_test_add.php .

Для отправки сообщения e-mail мне нужен другой скрипт в качестве программы обработки.

Листинг 4. mailout_send.php

В скрипте используется метод get_all() для выборки всех почтовых сообщений, а затем метод PHP mail() для поочередной отправки сообщений. После успешной рассылки всех сообщений, метод delete() удаляет эту отдельную запись из очереди.

Скрипт будет выполняться с заданным интервалом при помощи демона cron . Частота выполнения скрипта зависит от ваших потребностей и нужд вашего приложения.

Примечание: В информационном архиве PHP Extension and Application Repository (PEAR) имеется отличная практическая реализация системы очередей сообщений, которую можно загрузить бесплатно.

Ближе к делу

Замечательно, что найдено решение проблемы отправки почтовых сообщений, но как насчет чего-то более конкретного? Того, что позволит мне отправлять сообщения, генерировать отчеты и выполнять другие длительные операции без необходимости ждать при работе в браузере.

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

Листинг 5. generic.sql

Первая таблица, processing_items , содержит функции вызываемые программой обработки заданий. Во второй таблице, processing_args , приведены значения аргументов, передаваемых функциям как хэш-таблица посредством пар ключ/значение.

Эти две таблицы, как и таблица mailouts , имеют в качестве оболочки PHP-класс ProcessingItems .

Листинг 6. generic.php

Этот класс имеет три важных метода: add() , get_all() и delete() . Как и система mailouts , машина предварительной обработки данных использует add() , а обрабатывающий движок — get_all() и delete() .

Тестовый скрипт добавления элемента в обрабатывающийся фрагмент очереди приведен в Листинге 7.

Листинг 7. generic_test_add.php

В данном случая я обращаюсь к функции printvalue с аргументом value со значением foo . Я использую интерпретатор командной строки PHP для запуска скрипта и помещаю вызов метода в очередь. Затем я использую следующий скрипт обработки для выполнения метода.

Листинг 8. generic_process.php

Этот скрипт удивительно прост. Он берет обрабатываемые элементы, возвращенные методом get_all() , а затем использует call_user_func_array — внутреннюю функцию PHP — для вызова метода динамически с заданными аргументами. В этом случае вызывается локальная функция printvalue .

Для иллюстрации этой возможности я покажу, что происходит в командной строке:

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

Мысль о размещении имен функций PHP и их аргументов в БД вызывает у вас отвращение — альтернативой является включение карты схемы в PHP-код, содержащий соответствие имени «типа задания на обработку данных», хранящегося в БД, и действительной функции обработки PHP. Таким образом, если потом вы задумаете изменить серверную часть обработки PHP на что-то другое, программа будет работать, если совпадают строки «типа задания на обработку данных».

Отказ от использования баз данных

В завершение серии примеров программного кода я взгляну на проблему под другим углом, а именно, буду использовать файлы в директории, а не в БД для хранения пакетных заданий. Предлагая это, я не говорю вам «Делайте так, а не с помощью БД», а привожу альтернативный вариант проектного решения, к которому вы можете прибегнуть, (а можете этого и не делать) по своему усмотрению.

Несомненно, что схемы здесь нет, поскольку мы не используем БД. Поэтому я начну с класса, который содержит те же типы методов add() , get_all() и delete() , что и использованные в приведенном выше примере.

Листинг 9. batch_by_file.php

Класс BatchFiles имеет три базовых метода: add() , get_all() , и delete() . Вместо обращения к БД, класс читает и записывает файлы из директории с именем batch_items.

Для добавления нового элемента пакета я использую следующий программный код.

Листинг 10. batch_by_file_test_add.php

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

Наконец, вот код программы обработки.

Листинг 11. batch_by_file_processor.php

Данная программа практически полностью совпадает с версией для БД, изменены только некоторые имена классов и файлов.

Заключение

Как уже было отмечено ранее, хорошо развита поддержка обработки сообщений на серверах для выполнения пакетной обработки в фоновом режиме. Конечно, в некоторых случаях немного проще прибегнуть к вспомогательному потоку для обработки небольших заданий. Но несложно заметить, что при помощи таких традиционных инструментальных средств, как cron , MySQL, стандартный объектно-ориентированный PHP, а также Pear::DB, пакетные задания в PHP-приложениях просто создавать, использовать и поддерживать в рабочем состоянии.

Ресурсы для скачивания

Похожие темы

  • Оригинал статьи: Batch processing in PHP.
  • PHP.net — отличный ресурс для программистов на PHP.
  • Откройте для себя PEAR — PHP Extension and Application Repository, содержащий также Pear::DB.
  • PEAR Mail_Queue package — это основательная реализация очередей сообщений с машиной БД.

  • В справочном руководстве crontab приведено сложное, но подробное описание конфигурации cron .
  • Справочное руководство по PHP, в одном из разделов которого рассматривается использование PHP из командной строки. Изучение этого раздела поможет вам понять, как скрипт запускается демоном cron .
  • Узнайте больше о PHP, посетив раздел ресурсы по проекту PHP на IBM developerWorks.
  • Посетите раздел ПО с открытым исходным кодом на developerWorks для получения разнообразной информации о средствах и методах разработки ПО, инструментальных средств и обновлений проектов, что поможет вам в разработке технологий с открытым исходным кодом и использовании их с программными продуктами IBM.
  • Прослушайте интересные для разработчиков ПО интервью и дискуссии, посетив раздел подкасты на developerWorks.
  • Создайте свой следующий проект с помощью пробного ПО IBM, доступного на DVD или для загрузки.

Комментарии

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

Обработка запросов к БД при помощи PEAR::XML PHP

Обработка запросов с помощью PHP

Основы клиент-серверных технологий

В самом начале курса мы уже говорили о том, что PHP – это скриптовый язык, обрабатываемый сервером. Сейчас мы хотим уточнить, что же такое сервер, какие функции он выполняет и какие вообще бывают серверы. Если речь идет о сервере, невольно всплывает в памяти понятие клиента. Все потому, что эти два понятия неразрывно связаны. Объединяет их компьютерная архитектура клиент-сервер. Обычно, когда говорят «сервер», имеют в виду сервер в архитектуре клиент-сервер, а когда говорят «клиент» – имеют в виду клиент в этой же архитектуре. Так что же это за архитектура? Суть ее в том, чтобы разделить функции между двумя подсистемами: клиентом, который отправляет запрос на выполнение каких-либо действий, и сервером, который выполняет этот запрос. Взаимодействие между клиентом и сервером происходит посредством стандартных специальных протоколов, таких как TCP/IP и z39.50. На самом деле протоколов очень много, они различаются по уровням. Мы рассмотрим только протокол прикладного уровня HTTP (чуть позднее), поскольку для решения наших программистских задач нужен только он. А пока вернемся к клиент-серверной архитектуре и разберемся, что же такое клиент и что такое сервер.

Сервер представляет собой набор программ, которые контролируют выполнение различных процессов. Соответственно, этот набор программ установлен на каком-то компьютере. Часто компьютер, на котором установлен сервер, и называют сервером. Основная функция компьютера-сервера – по запросу клиента запустить какой-либо определенный процесс и отправить клиенту результаты его работы.

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

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

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

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

Существует множество типов серверов. Вот лишь некоторые из них.

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

Поисковый сервер предназначен для поиска информации в Internet.

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

Сервер WWW предназначен для работы в Internet.

Сервер баз данных выполняет обработку запросов к базам данных.

— Сервер защиты данных предназначен для обеспечения безопасности данных (содержит, например, средства для идентификации паролей).

Сервер приложений предназначен для выполнения прикладных процессов. С одной стороны взаимодействует с клиентами, получая задания, а с другой – работает с базами данных, подбирая необходимые для обработки данные.

Сервер удаленного доступа обеспечивает коллективный удаленный доступ к данным.

Мастер Йода рекомендует:  Шаблон проектирования Хранилище PHP

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

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

Из всех типов серверов нас в основном интересует сервер WWW. Часто его называют web-сервером, http-сервером или даже просто сервером. Что представляет собой web-сервер? Во-первых, это хранилище информационных ресурсов. Во-вторых, эти ресурсы хранятся и предоставляются пользователям в соответствии со стандартами Internet (такими, как протокол передачи данных HTTP). Как предоставляются данные в соответствии с этим протоколом, мы рассмотрим чуть позже. Работа с документами web-сервера осуществляется при помощи браузера (например, IE, Opera или Mozilla), который отсылает серверу запросы, созданные в соответствии с протоколом HTTP. В процессе выполнения задания сервер может связываться с другими серверами.

Далее в ходе лекции, говоря «сервер», мы будем подразумевать web-сервер.

В качестве примеров web-серверов можно привести сервер Apache группы Apache, Internet Information Server (IIS) компании Microsoft, SunOne фирмы Sun Microsystems,WebLogic фирмы BEA Systems, IAS (Inprise Application Server) фирмы Borland, WebSphere фирмы IBM, OAS (Oracle Application Server).

На рис. 4.1 и в таблице 4.1 приведена статистика использования различных серверов среди всех доменов Internet от NetCraft https://news.netcraft.com/.

Рис. 4.1. Статистика использования ведущих web-серверов

Как видно из приведенной таблицы, сервер Apache занимает лидирующие позиции. Все, что мы когда-либо будем говорить о web-серверах, ориентировано на Apache, если не указано иное. О том, как установить его на свой компьютер, мы уже рассказывали в самой первой лекции. А теперь, как было обещано, обратимся к протоколу HTTP.

Протокол HTTP и способы передачи данных на сервер

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

HTTP (HyperText Transfer Protocol, протокол передачи гипертекста) – это протокол прикладного уровня, разработанный для обмена гипертекстовой информацией в Internet.

HTTP предоставляет набор методов для указания целей запроса, отправляемого серверу. Эти методы основаны на дисциплине ссылок, где для указания ресурса, к которому должен быть применен данный метод, используется универсальный идентификатор ресурсов (Universal Resource Identifier) в виде местонахождения ресурса (Universal Resource Locator, URL) или в виде его универсального имени (Universal Resource Name, URN).

Сообщения по сети при использовании протокола HTTP передаются в формате, схожем с форматом почтового сообщения Internet (RFC-822) или с форматом сообщений MIME (Multipurpose Internet Mail Exchange).

HTTP используется для коммуникаций между различными пользовательскими программами и программами-шлюзами, предоставляющими доступ к существующим Internet-протоколам, таким как SMTP (протокол электронной почты), NNTP (протокол передачи новостей), FTP (протокол передачи файлов), Gopher и WAIS. HTTP разработан для того, чтобы позволять таким шлюзам через промежуточные программы-серверы (proxy) передавать данные без потерь.

Протокол реализует принцип запрос/ответ. Запрашивающая программа – клиент инициирует взаимодействие с отвечающей программой – сервером и посылает запрос, содержащий:

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

Ответ сервера содержит:

— строку состояния, в которую входит версия протокола и код возврата (успех или ошибка);

— сообщение (в форме, похожей на MIME), в которое входит информация сервера, метаинформация (т.е. информация о содержании сообщения) и тело сообщения.

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

Давайте рассмотрим более подробно, в какой форме отправляются запросы на сервер.

Форма запроса клиента

Клиент отсылает серверу запрос в одной из двух форм: в полной или сокращенной. Запрос в первой форме называется соответственно полным запросом, а во второй форме – простым запросом.

Простой запрос содержит метод доступа и адрес ресурса. Формально это можно записать так:

В качестве метода могут быть указаны GET, POST, HEAD, PUT, DELETE и другие. О наиболее распространенных из них мы поговорим немного позже. В качестве запрашиваемого URI чаще всего используется URL-адрес ресурса.

Пример простого запроса:

Здесь GET – это метод доступа, т.е. метод, который должен быть применен к запрашиваемому ресурсу, а https://phpbook.info/ – это URL-адрес запрашиваемого ресурса.

Полный запрос содержит строку состояния, несколько заголовков (заголовок запроса, общий заголовок или заголовок содержания) и, возможно, тело запроса. Формально общий вид полного запроса можно записать так:

Квадратные скобки здесь обозначают необязательные элементы заголовка, через вертикальную черту перечислены альтернативные варианты. Элемент содержит метод запроса и URI ресурса (как и простой запрос) и, кроме того, используемую версию протокола HTTP. Например, для вызова внешней программы можно задействовать следующую строку состояния:

POST https://phpbook.info/cgi-bin/test HTTP/1.0

В данном случае используется метод POST и протокол HTTP версии 1.0.

В обеих формах запроса важное место занимает URI запрашиваемого ресурса. Чаще всего URI используется в виде URL-адреса ресурса. При обращении к серверу можно применять как полную форму URL, так и упрощенную.

Полная форма содержит тип протокола доступа, адрес сервера ресурса и адрес ресурса на сервере (рисунок 4.2).

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

Рис. 4.2. Полная форма URL

Далее мы рассмотрим наиболее распространенные методы отправки запросов.

Как уже говорилось, любой запрос клиента к серверу должен начинаться с указания метода. Метод сообщает о цели запроса клиента. Протокол HTTP поддерживает достаточно много методов, но реально используются только три: POST, GET и HEAD. Метод GET позволяет получить любые данные, идентифицированные с помощью URI в запросе ресурса. Если URI указывает на программу, то возвращается результат работы программы, а не ее текст (если, конечно, текст не есть результат ее работы). Дополнительная информация, необходимая для обработки запроса, встраивается в сам запрос (в строку статуса). При использовании метода GET в поле тела ресурса возвращается собственно затребованная информация (текст HTML-документа, например).

Существует разновидность метода GET – условный GET. Этот метод сообщает серверу о том, что на запрос нужно ответить, только если выполнено условие, содержащееся в поле if-Modified-Since заголовка запроса. Если говорить более точно, то тело ресурса передается в ответ на запрос, если этот ресурс изменялся после даты, указанной в if-Modified-Since.

Метод HEAD аналогичен методу GET, только не возвращает тело ресурса и не имеет условного аналога. Метод HEAD используют для получения информации о ресурсе. Это может пригодиться, например, при решении задачи тестирования гипертекстовых ссылок.

Метод POST разработан для передачи на сервер такой информации, как аннотации ресурсов, новостные и почтовые сообщения, данные для добавления в базу данных, т.е. для передачи информации большого объема и достаточно важной. В отличие от методов GET и HEAD, в POST передается тело ресурса, которое и является информацией, получаемой из полей форм или других источников ввода.

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

Использование HTML-форм для передачи данных на сервер

Как передавать данные серверу? Для этого в языке HTML есть специальная конструкция – формы. Формы предназначены для того чтобы получать от пользователя информацию. Например, вам нужно знать логин и пароль пользователя для того, чтобы определить, на какие страницы сайта его можно допускать. Или вам необходимы личные данные пользователя, чтобы была возможность с ним связаться. Формы как раз и применяются для ввода такой информации. В них можно вводить текст или выбирать подходящие варианты из списка. Данные, записанные в форму, отправляются для обработки специальной программе (например, скрипту на PHP) на сервере. В зависимости от введенных пользователем данных эта программа может формировать различные web-страницы, отправлять запросы к базе данных, запускать различные приложения и т.п.

Разберемся с синтаксисом HTML-форм. Возможно, многие с ним знакомы, но мы все же повторим основные моменты, поскольку это важно.

Итак, для создания формы в языке HTML используется тег FORM. Внутри него находится одна или несколько команд INPUT. С помощью атрибутов action и method тега FORM задаются имя программы, которая будет обрабатывать данные формы, и метод запроса, соответственно. Команда INPUT определяет тип и различные характеристики запрашиваемой информации. Отправка данных формы происходит после нажатия кнопки input типа submit. Создадим форму для регистрации участников заочной школы программирования.

После обработки браузером этот файл будет выглядеть примерно так:

Рис. 4.3. Пример html-формы

Вот так создаются и выглядят HTML-формы. Будем считать, что мы научились или вспомнили, как их создавать. Как мы видим, в форме можно указывать метод передачи данных. Посмотрим, что будет происходить, если указать метод GET или POST, и в чем будет разница.

При отправке данных формы с помощью метода GET содержимое формы добавляется к URL после знака вопроса в виде пар имя=значения, объединенных с помощью амперсанта &:

Здесь action – это URL-адрес программы, которая должна обрабатывать форму (это либо программа, заданная в атрибуте action тега form, либо сама текущая программа, если этот атрибут опущен). Имена name1, name2, name3 соответствуют именам элементов формы, а value1, value2, value3 – значениям этих элементов. Все специальные символы, включая = и &, в именах или значениях этих параметров будут опущены. Поэтому не стоит использовать в названиях или значениях элементов формы эти символы и символы кириллицы в идентификаторах.

Если в поле для ввода ввести какой-нибудь служебный символ, то он будет передан в его шестнадцатеричном коде, например, символ $ заменится на %24. Так же передаются и русские буквы.

Для полей ввода текста и пароля (это элементы input с атрибутом type=text и type=password), значением будет то, что введет пользователь. Если пользователь ничего не вводит в такое поле, то в строке запроса будет присутствовать элемент name=, где name соответствует имени этого элемента формы.

Для кнопок типа checkbox и radio button значение value определяется атрибутом VALUE в том случае, когда кнопка отмечена. Не отмеченные кнопки при составлении строки запроса игнорируются целиком. Несколько кнопок типа checkbox могут иметь один атрибут NAME (и различные VALUE), если это необходимо. Кнопки типа radio button предназначены для одного из всех предложенных вариантов и поэтому должны иметь одинаковый атрибут NAME и различные атрибуты VALUE.

В принципе создавать HTML-форму для передачи данных методом GET не обязательно. Можно просто добавить в строку URL нужные переменные и их значения.

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

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

Для метода POST

Содержимое формы кодируется точно так же, как для метода GET (см. выше), но вместо добавления строки к URL содержимое запроса посылается блоком данных как часть операции POST. Если присутствует атрибут ACTION, то значение URL, которое там находится, определяет, куда посылать этот блок данных. Этот метод, как уже отмечалось, рекомендуется для передачи больших по объему блоков данных.

Информация, введенная пользователем и отправленная серверу с помощью метода POST, подается на стандартный ввод программе, указанной в атрибуте action, или текущему скрипту, если этот атрибут опущен. Длина посылаемого файла передается в переменной окружения CONTENT_LENGTH, а тип данных – в переменной CONTENT_TYPE.

Передать данные методом POST можно только с помощью HTML-формы, поскольку данные передаются в теле запроса, а не в заголовке, как в GET. Соответственно и изменить значение параметров можно, только изменив значение, введенное в форму. При использовании POST пользователь не видит передаваемые серверу данные.

Основное преимущество POST запросов – это их большая безопасность и функциональность по сравнению с GET-запросами. Поэтому метод POST чаще используют для передачи важной информации, а также информации большого объема. Тем не менее не стоит целиком полагаться на безопасность этого механизма, поскольку данные POST запроса также можно подделать, например создав html-файл на своей машине и заполнив его нужными данными. Кроме того, не все клиенты могут применять метод POST, что ограничивает варианты его использования.

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

— REMOTE_ADDR – IP-адрес хоста (компьютера), отправляющего запрос;

— REMOTE_HOST – имя хоста, с которого отправлен запрос;

— HTTP_REFERER – адрес страницы, ссылающейся на текущий скрипт;

— REQUEST_METHOD – метод, который был использован при отправке запроса;

— QUERY_STRING – информация, находящаяся в URL после знака вопроса;

— SCRIPT_NAME – виртуальный путь к программе, которая должна выполняться;

— HTTP_USER_AGENT – информация о браузере, который использует клиент

Обработка запросов с помощью PHP

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

Внутри PHP-скрипта имеется несколько способов получения доступа к данным, переданным клиентом по протоколу HTTP. До версии PHP 4.1.0 доступ к таким данным осуществлялся по именам переданных переменных (напомним, что данные передаются в виде пар «имя переменной, символ «=», значение переменной»). Таким образом, если, например, было передано first_name=Nina, то внутри скрипта появлялась переменная $first_name со значением Nina. Если требовалось различать, каким методом были переданы данные, то использовались ассоциативные массивы $HTTP_POST_VARS и $HTTP_GET_VARS, ключами которых являлись имена переданных переменных, а значениями – соответственно значения этих переменных. Таким образом, если пара first_name=Nina передана методом GET, то $HTTP_GET_VARS[«first_name»]=»Nina».

Использовать в программе имена переданных переменных напрямую небезопасно. Поэтому было решено начиная с PHP 4.1.0 задействовать для обращения к переменным, переданным с помощью HTTP-запросов, специальный массив – $_REQUEST. Этот массив содержит данные, переданные методами POST и GET, а также с помощью HTTP cookies. Это суперглобальный ассоциативный массив, т.е. его значения можно получить в любом месте программы, используя в качестве ключа имя соответствующей переменной (элемента формы).

Пример 4.2. Допустим, мы создали форму для регистрации участников заочной школы программирования, как в приведенном выше примере. Тогда в файле 1.php, обрабатывающем эту форму, можно написать следующее:

Тогда, если в форму мы ввели имя «Вася», фамилию «Петров» и выбрали среди всех курсов курс по PHP, на экране браузера получим такое сообщение:

Здравствуйте, Вася Петров!
Вы выбрали для изучения курс по PHP


После введения массива $_REQUEST массивы $HTTP_POST_VARS и $HTTP_GET_VARS для однородности были переименованы в $_POST и $_GET соответственно, но сами они из обихода не исчезли из соображений совместимости с предыдущими версиями PHP. В отличие от своих предшественников, массивы $_POST и $_GET стали суперглобальными, т.е. доступными напрямую и внутри функций и методов.

Приведем пример использования этих массивов. Допустим, нам нужно обработать форму, содержащую элементы ввода с именами first_name, last_name, kurs (например, форму form.html, приведенную выше). Данные были переданы методом POST, и данные, переданные другими методами, мы обрабатывать не хотим. Это можно сделать следующим образом:

Тогда на экране браузера, если мы ввели имя «Вася», фамилию «Петров» и выбрали среди всех курсов курс по PHP, увидим сообщение, как в предыдущем примере:

Здравствуйте, Вася Петров!
Вы выбрали для изучения курс по PHP

Для того чтобы сохранить возможность обработки скриптов более ранних версий, чем PHP 4.1.0, была введена директива register_globals, разрешающая или запрещающая доступ к переменным непосредственно по их именам. Если в файле настроек PHP параметр register_globals=On, то к переменным, переданным серверу методами GET и POST, можно обращаться просто по их именам (т.е. можно писать $first_name). Если же register_globals=Off, то нужно писать $_REQUEST[«first_name»] или $_POST[«first_name»], $_GET[«first_name»], $HTTP_POST_VARS[«first_name»], $HTTP_GET_VARS[«first_name»]. С точки зрения безопасности эту директиву лучше отключать (т.е. register_globals=Off). При включенной директиве register_globals перечисленные выше массивы также будут содержать данные, переданные клиентом.

Иногда возникает необходимость узнать значение какой-либо переменной окружения, например метод, использовавшийся при передаче запроса или IP-адрес компьютера, отправившего запрос. Получить такую информацию можно с помощью функции getenv(). Она возвращает значение переменной окружения, имя которой передано ей в качестве параметра.

Мастер Йода рекомендует:  Ужесточение правил монетизации YouTube-каналов

Отправка запросов к базе данных в PHP

В этой статье мы научимся отправлять запросы к базе данных через PHP. Данная статья очень важная, и её необходимо Вам обязательно понять. Однако, успокою Вас — материал очень простой, поэтому затруднений быть не должно.

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

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

query(‘INSERT INTO mytable (name, email) VALUES («MyName», «myname@mail.ru»)’);
$mysqli->close();
?>

В данном примере мы подключились к базе данных, проверили успешность подключения, отправили запрос с помощью метода query(), а затем закрыли подключение. Как видите, всё очень просто. Для отправки любых SQL-запросов достаточно всего одного метода — query(), поэтому в данном случае всё безумно просто.

Теперь чуть-чуть усложним задачу. Давайте с Вами разберём запросы, которые возвращают result_set — результат. Самый популярный запрос, возврающающий result_set — это выборка данных из таблицы. В следующем примере мы с Вами сделаем выборку данных, а затем выведем результат:

query(‘SELECT * FROM mytable’);
while ($row = $result_set->fetch_assoc()) <
print_r($row);
echo «
«;
>
$result_set->close();
$mysqli->close();
?>

Для начала немного поясню, что из себя представляет result_set. Result_set — это таблица с результатом. У этой таблицы есть набор записей (строки таблицы). И для вывода всех записей надо перебрать каждую строку таблицы и вывести её. А теперь поясняю пример: после отправки запроса у нас формируется result_set. Затем мы в цикле присваиваем переменной row значение очередной строки, то есть одномерный массив, который возвращает метод fetch_assoc(). Когда все строки закончатся, метод fetch_assoc() вернёт false, и будет произведён выход из цикла. Внутри цикла while мы просто выводим массив с использованием отладочной функции print_r(), хотя, безусловно, можно было бы вывести с использованием foreach, но сейчас это не нужно.

Давайте кратко подведём итог, как нужно работать с result_set:

  1. Получить result_set, отправив соответствующий запрос к базе данных.
  2. В цикле на каждой итерации присваивать следующую строку (запись) из result_set с использованием метода fetch_assoc() некоторой переменной row. Дальше Вы можете работать с этой переменной как с одномерным ассоциативным массивом, у которого ключи — это названия полей таблицы, а значения соответствуют текущей записи.
  3. Обязательно закройте result_set методом close(), чтобы осводить ресурсы.

Как Вы заметили, метод fetch_assoc() возвращает всегда следующую запись. То есть сначала 1-ю, потом 2-ю, потом 3-ю и так далее. Если у Вас есть неплохой опыт программирования, то Вы сразу догадаетесь, что это происходит благодаря внутреннему указателю, который Вы, разумеется, можете двигать. Где это используется? Например, это может использоваться, когда Вам необходимо поработать с result_set не 1, а 2 и более раз. Чтобы заново не формировать тот же запрос, можно просто передвинуть указатель в начало. И тогда можно снова заниматься перебором result_set с помощью метода fetch_assoc().

Для изменения положения указателя существует метод data_seek(), который принимает целое число от до «количества записей — 1«, соответственно указатель встаёт на соответствующую параметру запись:

query(‘SELECT * FROM mytable’);
$result_set->num_rows;
while ($row = $result_set->fetch_assoc()) <
print_r($row);
echo «
«;
>
$result_set->data_seek(0);
while ($row = $result_set->fetch_assoc()) <
print_r($row);
echo «
«;
>
$result_set->close();
$mysqli->close();
?>

В этом примере мы вывели количество записей в result_set с помощью свойства num_rows. А также познакомились с методом data_seek(). То есть мы перебрали весь результат, затем вернули указатель на 0-ю запись и вновь перебрали результат.

В этой статье мы с Вами повторили подключение к базе данных и закрытие подключения. А также узнали, как отправлять запросы к базе данных через PHP. Узнали, как получать result_set и как работать с ним. Это всё, что Вам необходимо знать для успешной работы с MySQL в PHP.

XML и MySQL

Содержание


Введение

Сегодня многие приложения используют данные формата XML. Ряд приложений имеет встроенные средства для выгрузки данных в XML-файлы. MySQL таких средств не имеет. Поэтому обмен данными между MySQL БД и XML-документом осуществляется средствами языка, на котором создается приложение, использующее БД (например, PHP).

Перечислим основные возможности использования технологии XML с сервером MySQL:


    XML как средство обмена данными между приложениями. Результат выполнения SQL-запроса оформляется как XML-документ. Последний представляет собой платформенно-независимый файл формата ASCII и может быть прочитан другими приложениями (не обязательно СУБД). Эти приложения могут использовать стандартные XML-инструменты (так называемые «парзеры» — от английского «parser»«синтаксический анализатор») для восстановления исходных данных из XML-документов. Таким образом, XML служит интерфейсом между MySQL и другими приложениями. Этот интерфейс может быть двусторонним. Данные, генерируемые приложениями, могут оформляться как XML-документы, которые затем будут анализироваться (средствами языка того приложения, которое использует MySQL БД) и извлеченные данные будут заноситься в таблицы БД.

XML как средство передачи данных в web-среде. Как уже было сказано, XML может служить средством обмена данными между приложениями. При этом четкая (и притом расширяемая) структура XML-документов и платформенно-независимый (ASCII) формат делает их использование особенно удобным для применения в клиент-серверных приложениях, в частности, в web-среде. Например, клиент (браузер) может служить источником SQL-запроса к MySQL БД. Этот запрос обрабатывается средствами серверного (например, PHP) сценария, который устанавливает соединение с БД и обеспечивает выполнение запроса. Информация, получаемая (с использованием MySQL БД), преобразуется (опять-таки серверным сценарием) в XML-документ, который отправляется клиенту и обрабатывается клиентскими средствами.

Использование XML для динамической генерации HTML-документов. Язык HTML (HyperText MarkUp Language), будучи лишь средством форматирования (буквально: «разметки») гипертекстовых документов, плохо приспособлен для работы с данными. Между тем, XML (Extensible MarkUp Language), т.е. «расширяемый язык разметки«, удобен как для хранения, так и для форматирования данных. Так, XML-документ (например, содержащий данные, полученные из БД в результате выполнения SQL-запроса) может использоваться для динамической генерации HTML-, WML-, или TXT-документов, которые затем будут читаться браузерами клиентских компьютеров или мобильных беспроводных устройств или выводиться на печать. (Конвертировать же данные из HTML-документа непосредственно в файлы других форматов невозможно.)

  • Непосредственное хранение XML-файлов в БД. XML-файлы можно непосредственно хранить в БД. Например, для создания писем удобно хранить шаблоны писем и собственно данные.


  • Ниже мы рассмотрим реализацию перечисленных возможностей использования XML на примерах.
    К началу

    Оформление результатов выполнения SQL-запроса в виде XML-файла

    Пусть в нашей БД имеется таблица animal :

    SQL-запрос на извлечение данных из этой таблицы имеет вид:

    Мы ориентируемся на использование СУБД MySQL Server и PHP. Поэтому php-сценарий, выполняющий запрос, должен иметь вид:

    Мы подошли к вопросу о том, как преобразовать полученный объект в XML-файл. Универсальным способом является непосредственное использование XML-тэгов. (Вместе с тем, некоторые языки программирования, например, Perl содержат встроенные модули для выполнения этого пребразования.)

    Используем непосредственное написание XML-тэгов. Итак,

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

    Таким образом, данные, извлеченные (с помощью SQL-запроса) из таблицы представлены в XML-формате.

    — это корневой элемент; элементы создаются для каждой строки объекта recordset; объекты и содержаьт элементы соответсвующих стоолбцов таблицы.

    Преимущество такого способа представления данных (полученных с помощью SQL-запроса) — это простота.
    Недостатки:

    • Необходимо знать структуру таблицы, из которой извлекаются данные (в частности, имена столбцов).
    • Здесь не предусмотрено кодирование специальных символов, которые могут содержаться в полях таблицы (например, ‘ К началу


    Создание XML-файла

    Мы преобразовали данные (извлеченные из MySQL БД) в XML-формат. Результирующий XML-код читается браузером и данные отображаются в окне: Тем самым, мы убедились, что преобразование прошло успешно. Но нам нужно сохранить динамически созданный XML-код в отдельном файле. С этой целью преобразуем наш сценарий конвертации данных, используя функции PHP для работы с файлами:

    Мы получили файл animals.xml, открыв который в браузере, мы увидим:

    Чтение XML-файла

    Мы научились сохранять данные (извлеченные из БД) в XML-формате. Теперь нужно решить обратную задачу: научиться читать данные (с целью их использования в MySQL БД). Для выполнения этой задачи нужно знать структуру XML-файла и структуру таблицы, в которую будут помещаться (читаемые из файла) данные. Итак, прочитаем и обработаем данные из файла animal.xml, а затем внесем их в таблицу, имеющую ту же структуру, что и таблица animal. (Пусть она называется zveri. Понятно, что эта таблица может находиться в другой БД,на другом компьютере, т.е. чтению XML-файла обычно предшествует его перемещение.)

    Синтаксический анализ (parsing) XML-файла осуществляется так назваемыми парзерами, т.е. специально предназначенными для этого модулями. Различают парзеры низкого и высокого уровней. Последние (например, XML:DOMDocument Object Model) позволяют конверитровать весь XML-документ в некоторую структуру (в опреативной памяти компьютера). Это, в свою очередь, позволяет затем обращаться к строкам этой структуры (как и при обработке объекта recordset серверным сценарием). Другие модули (в частности, основанные на технологии SAXSimple API for XML) осуществляют так назыываемое потоковое чтение, возвращая элементы данных по мере чтения. Преимуществом первого подхода является, например, возможность проверки соотношений между данными различных столбцов. Однако при больших объемах данных лучше использовать потоковое чтение — так как этот подход позволяет сократить объем необходимой оперативной памяти (не нужно хранить сразу весь документ.)

    Результат будет выглядеть (в браузере) так:

    Лекции по веб-программированию

    База данных – это инструмент, который позволяет хранить и обрабатывать контент сайта, т.е. все медийные материалы, которые показываются пользователю в браузере. С помощью СУБД осуществляется выборка, добавление, удаление и изменение данных. Также с использованием базы данных с легкостью решаются такие задачи как поиск по сайту, разбиение на страницы, регистрация и авторизация пользователей. Именно поэтому в основные инструменты веб-разработчика включается СУБД.

    MySQL — это популярная реляционная клиент-серверная СУБД, используемая в разных приложениях. Стандартным языком управления реляционных баз данных является SQL. SQL означает язык структурированных запросов (Structured Query Language), который MySQL использует для коммуникации с другими программами. Сверх того, MySQL имеет свои собственные расширенные функции SQL для того чтобы обеспечить пользователям дополнительный функционал.

    Любая программа на языке PHP, которая собирается работать с MуSQL базой данных, должна состоять из следующих обязательных базовых шагов:
    1. Установить связь с MySQL сервером.
    2. Выбрать базу данных для работы.
    3. Посылать команды MYSQL серверу и получать ответы.
    4. Обработать результаты.
    5. Закрыть связь с MySQL сервером.

    Реализовать эти действия можно несколькими способами:
    1. Используя стандартные классические функции обращения к БД MySQL.
    2. Используя современные функции из расширения mysqli для версий начиная с PHP 5 и MySQL 4.1.
    3. Используя классы и методы из расширения mysqli для версий начиная с PHP 5 и MySQL 4.1.

    Рассмотрим на примерах как реализуется доступ к БД MySQL каждым из указанных способов.

    Классический доступ к БД MySQL

    Современное подключение к БД MySQL

    Использование функций из расширения mysqli ускоряет большинство операций доступа к БД, иногда достигая 40-кратного увеличения производительности по сравнению с классическим методом. Также повышена безопасность работы с данными и добавлены новые функции.

    Подключение к БД MySQL с использованием классов и методов

    Объектно-ориентированный интерфейс предоставляет немного более лаконичный и менее восприимчивый к ошибкам способ подключения к базе данных.

    Использование шаблонов запросов при обращении к базе данных

    Подготовленные выражения или шаблоны предоставляют разработчикам возможность создавать запросы, которые являются более безопасными, имеют более высокую производительность и более удобны в написании.

    Процесс работы с шаблонами таков:

    1. Подготовить для сервера MySQL шаблон запроса с параметрами.
    2. Привязать переменные PHP к параметрам в заготовке запроса.
    3. Дать команду серверу на выполнение запроса.
    4. Запросить получение нового ряда данных в указанные переменные.

    PHP: PDO быстрый старт, работа с MySQL

    Содержание:

    PDO (PHP Data Objects) — расширение PHP, которое реализует взаимодействие с базами данных при помощи объектов. Профит в том, что отсутствует привязка к конкретной системе управления базами данных. PDO поддерживает СУБД: MySQL, PostgreSQL, SQLite, Oracle, Microsoft SQL Server и другие.

    Официальный мануал по PHP PDO здесь . Там же можно найти и сам класс PDO .

    Почему стоит использовать PDO

    Функции mysql в PHP для работы с БД давно уже устарели, на сегодняшний день желательно использовать mysqli или PDO (PHP Data Objects). Кроме того, mysqli — эта библиотека, которая по большому счёту, не предназначена для использования напрямую в коде. Она может послужить хорошим строительным материалом для создания библиотеки более высокого уровня. При работе с mysqli следует также помнить об обеспечении безопасности вашего приложения, в частности о защите от SQL-инъекций. В случае использования PDO (с его подготовленными запросами), такая защита идёт уже «из коробки», главное правильно применить необходимые методы.

    Тестовая база данных с таблицей

    Установка PDO

    Проверить доступные драйвера

    Соединение с базой данных

    Соединения устанавливаются автоматически при создании объекта PDO от его базового класса.

    При ошибке подключения PHP выдаст ошибку:

    В этом примере подключения мы используем конструкцию try. catch . Многие спорят о целесообразности её использования. Лично я использую try. catch , она мне не мешает.

    Подготовленные и прямые запросы

    В PDO два способа выполнения запросов:

    • Прямой — состоит из одного шага;
    • Подготовленный — состоит из двух шагов.

    Прямые запросы

    • query() используется для операторов, которые не вносят изменения, например SELECT . Возвращает объект PDOStatemnt , из которого с помощью методов fetch() или fetchAll извлекаются результаты запроса. Можно его сравнить с mysql resource , который возвращала mysql_query() .
    • exec() используется для операторов INSERT, DELETE, UPDATE . Возвращает число обработанных запросом строк.

    Прямые запросы используются только в том случае, если в запросе отсутствуют переменные и есть уверенность, что запрос безопасен и правильно экранирован.

    Подготовленные запросы

    Если же в запрос передаётся хотя бы одна переменная, то этот запрос в обязательном порядке должен выполняться только через подготовленные выражения . Что это значит? Это обычный SQL запрос, в котором вместо переменной ставится специальный маркер — плейсхолдер. PDO поддерживает позиционные плейсхолдеры ( ? ), для которых важен порядок передаваемых переменных, и именованные ( :name ), для которых порядок не важен. Примеры:

    Чтобы выполнить такой запрос, сначала его надо подготовить с помощью метода prepare() . Она также возвращает PDO statement , но ещё без данных. Чтобы их получить, надо исполнить этот запрос, предварительно передав в него наши переменные. Передать можно двумя способами: Чаще всего можно просто выполнить метод execute() , передав ему массив с переменными:

    Как видно, в случае именованных плейсхолдеров в execute() должен передаваться массив, в котором ключи должны совпадать с именами плейсхолдеров. После этого можно извлечь результаты запроса:

    ВАЖНО! Подготовленные запросы — основная причина использовать PDO, поскольку это единственный безопасный способ выполнения SQL запросов, в которых участвуют переменные.

    Получение данных. Метод fetch()

    Мы уже выше познакомились с методом fetch() , который служит для последовательного получения строк из БД. Этот метод является аналогом функции mysq_fetch_array() и ей подобных, но действует по-другому: вместо множества функций здесь используется одна, но ее поведение задается переданным параметром. В подробностях об этих параметрах будет написано в другой заметке , а в качестве краткой рекомендации посоветую применять fetch() в режиме FETCH_LAZY

    В этом режиме не тратится лишняя память, и к тому же к колонкам можно обращаться любым из трех способов — через индекс, имя, или свойство (через -> ). Недостатком же данного режима является то, что он не работает с fetchAll()

    Получение данных. Метод fetchColumn()

    Также у PDO statement есть метод для получения значения единственной колонки. Очень удобно, если мы запрашиваем только одно поле — в этом случае значительно сокращается количество кода:

    Получение данных. Метод fetchAll()

    PDO и оператор LIKE

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

    Здесь может вознинуть проблема! Поиск может не работать, потому как из базы у вас приходят данные в неправильной кодировке. Необходимо добавить кодировку в подключение, если она там не указана!

    PDO и оператор LIMIT

    Важно! Когда PDO работает в режиме эмуляции, все данные, которые были переданы напрямую в execute() , форматируются как строки. То есть, эскейпятся и обрамляются кавычками. Поэтому LIMIT . превращается в LIMIT ’10’, ’10’ и очевидным образом вызывает ошибку синтаксиса и, соответственно, пустой массив данных.

    Решение #1 : Отключить режим эмуляции:

    Решение #2 : Биндить эти цифры через bindValue() , принудительно выставляя им тип PDO::PARAM_INT :

    PDO и оператор IN

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

    Добавление записей

    Изменение записей

    Удаление записей

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

    Важно! Транзакции в PDO работают только с таблицами InnoDB

    В данной заметке мы познакомились с основными понятиями PDO, его установкой, подключением к БД и самые простые возможности выборки, изменения и удаления данных. В следующих заметках мы рассмотрим ещё несколько тем, касающихся PDO.

    Добавить комментарий