
Приветствую всех!
Как я и обещал, мы продолжаем разработку приложения для проверки URL и сегодня займемся непосредственно выполнением проверок.
Чтобы немного облегчить себе жизнь, проверки мы будем выполнять с помощью библиотеки cURL.
Эта библиотека предоставляет очень широкие возможности для работы с web ресурсами. Поддерживаются редиректы, отправка данных, установка заголовков, автоматически собирается статистика и многое другое. Естественно, все возможности гибко настраиваются. В общем, при желании можно полностью имитировать работу человека в интернете.
Теперь нам нужно подключить эту библиотеку к PHP. Для этого в файле php.ini нужно убрать «;» в начале строки extension=php_curl.dll. После этого в сведениях, которые возвращает функция phpinfo() появится раздел curl и в нем параметр — cURL support: enabled.
Библиотека подключена и можно начинать ее использовать.
Для начала приведу небольшой пример, иллюстрирующий основные принципы работы с библиотекой на PHP.
$ch = curl_init(); // инициализация curl_setopt($ch, CURLOPT_URL, ‘http://www.google.com’); // устанавливаем URL curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);// разрешаем редирект curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); // указывает, что функция curl_exec должна вернуть полученный ответ, а не отправить его сразу браузеру $result = curl_exec($ch); // запуск curl_close($ch); echo $result;
Здесь все достаточно просто. Функция curl_init инициализирует библиотеку и создает объект для работы с ней ($ch). После этого с помощью функции curl_setopt можно настроить библиотеку. В первом параметре этой функции передаем созданный объект, во втором – указываем имя параметра, который нужно настроить, а в третьем – значение параметра.
После этого вызываем функцию curl_exec, которая и выполняет всю работу, т.е. отправляет запрос и получает данные.
Возвращаемся к нашему приложению.
Как я и говорил в прошлый раз, всю работу по проверке URL выполняет метод ping. Рассмотрим его подробнее.
function ping($urlId = 0) {
$this->load->model('urlmodel');
$this->load->model('resultmodel');
$urls = array();
if ($urlId == 0) {
//получаем полный список URL из БД
$urls = $this->urlmodel->getAllUrls();
}
else {
//ищем выбранный URL
$urls = $this->urlmodel->getUrlById($urlId);
}
if ($urls !== FALSE) {
//создаем обработчик для параллельной работы с URL'ами
$mh = curl_multi_init();
//создаем обработчики для каждого отдельного URL и добавляем их в $mh
$handles = array();
for ($i = 0; $i < count($urls); $i++) {
$handles[$i] = curl_init();
curl_setopt($handles[$i], CURLOPT_URL, $urls[$i]['URL']);
curl_setopt($handles[$i], CURLOPT_RETURNTRANSFER, 1);
curl_setopt($handles[$i], CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($handles[$i], CURLOPT_TIMEOUT, 10);
curl_setopt($handles[$i], CURLOPT_HEADER, 0);
//если используется прокси, нужно указать его порт и ip
//curl_setopt($handles[$i], CURLOPT_PROXYPORT, "8080");
//curl_setopt($handles[$i], CURLOPT_PROXY, "192.168.0.1");
curl_multi_add_handle($mh, $handles[$i]);
}
//запускаем обработку
$running = null;
do {
curl_multi_exec($mh, $running);
} while ($running > 0);
//получаем данные и сохраняем их в БД
for ($i = 0; $i < count($urls); $i++) {
$urlInfo = curl_getinfo($handles[$i]);
$resData['urlId'] = $urls[$i]['id'];
if ($urlInfo['speed_download'] != 0) {
$resData['result'] = 1;
}
else {
$resData['result'] = 0;
}
$resData['responsetime'] = $urlInfo['total_time'];
$resData['responselength'] = $urlInfo['size_download'];
$resData['responsespeed'] = $urlInfo['speed_download'];
$this->resultmodel->saveResults($resData);
}
//закрываем обработчики
for ($i = 0; $i < count($handles); $i++) {
curl_multi_remove_handle($mh, $handles[$i]);
}
if ($urlId == 0) {
$this->index();
}
else {
$this->urldetails($urlId);
}
}
}
Как видите, метод довольно объемный и достаточно сильно отличается от первого примера. Но обо всем по порядку.
После загрузки моделей, мы проверяем значение параметра $urlId. Если он равен нулю, то выполняем проверку всех URL в базе данных, если нет – проверяем только заданный URL.
Теперь нам нужно проверить найденные в базе данных URL. Если этот URL один, то все довольно просто, можно ограничиться кодом из первого примера, но у нас может быть несколько десятков URL. Запустить проверки в цикле, конечно, возможно, но это скрипт при этом может выполняться довольно долго. А в большинстве случаев время работы скриптов ограничено (параметр max_execution_time).
Поэтому здесь мы используем функцию curl_multi_init() (строка 15) для параллельной обработки нескольких запросов. По-сути, объект, который создает curl_multi_init, является контейнером для обычных обработчиков.
После этого в цикле (строки 18-30) с помощью curl_init мы создаем массив объектов для работы с каждым URL, настраиваем его и с помощью функции curl_multi_add_handle добавляем в контейнер (строка 29).
Обратите внимание на параметр CURLOPT_TIMEOUT (строка 23). Я установил его равным 10 секундам. Это время в течении которого cURL будет ждать ответ сервера. Значение я взял «с потолка», поэтому если оно вас не устраивает, можете спокойно его изменить.
Сейчас все готово для начала проверок. Запуск выполняется функцией curl_multi_exec, которая принимает два параметра. Первый – созданный объект с обработчиками, второй – переменная, указывающая завершилась обработка или нет.
Функция curl_multi_exec вызывается внутри цикла, выход из которого выполняется, когда переменная $running будет равна нулю, т.е. завершится обработка всех URL.
После этого нам остается только получить данные о проверках с помощью функции curl_getinfo (строка 38) и сформировать массив с результатами ($resData).
На завершающем этапе мы сохраняем данные в БД (строка 49), с помощью функции curl_multi_remove_handle закрываем обработчики (строка 53) и показываем посетителю страницу, с которой был вызван метод (строки 55-60).
Все. Метод для выполнения проверок готов. В следующий раз мы рассмотрим создание представлений, т.е. страниц сайта.
До встречи!
P.S. Ссылки на все статьи и примеры цикла я публикую здесь.


