Приветствую всех!
Как я и обещал, мы продолжаем разработку приложения для проверки 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. Ссылки на все статьи и примеры цикла я публикую здесь.