Довольно часто владельцы сайтов просят поставить на свои проекты индикаторы курсов валют и их динамику. Можно воспользоваться готовыми информерами, но они не всегда позволяют должным образом настроить внешний вид.
Поэтому сейчас мы сделаем парсер курса валют на php с сайта cbr.ru, отобразим динамику изменения курса и в конце закешируем полученные данные для эффективного использования в 1с-Битрикс.
Получаем и обрабатываем данные
Самые свежие данные мы будем получать из xml-файла, который совершенно бесплатно предоставляет нам сайт cbr.ru. Адрес файла имеет вид — http://www.cbr.ru/scripts/XML_dynamic.asp?date_req1=10/02/2011&date_req2=26/02/2011&VAL_NM_RQ=R01235
Здесь date_req1 — дата начала периода; date_req2 — дата конца периода, за который нужна динамика; VAL_NM_RQ — идентификатор валюты (R01235 для USD, R01239 для EUR)
Структура полученного xml-файла такова:
<ValCurs ID="R01239" DateRange1="18/02/2011" DateRange2="19/02/2011" name="Foreign Currency Market Dynamic"> <Record Date="18.02.2011" Id="R01239"> <Nominal> 1 </Nominal> <Value> 39,6821 </Value> </Record> <Record Date="19.02.2011" Id="R01239"> <Nominal> 1 </Nominal> <Value> 39,7682 </Value> </Record> </ValCurs>
Как мы видим, записи идут в порядке возрастания даты и нужное значение хранится в теге и его легко получить регулярным выражением.
// формируем 2 даты - "завтра" и несколько дней назад $curDate = date('d/m/Y', mktime(0,0,0,date("n"),date("j")+1,date("Y"))); $curDate2 = date('d/m/Y', mktime(0,0,0,date("n"),date("j")-10,date("Y"))); // xml с сайта ЦБ РФ $currencyXML = file_get_contents('http://www.cbr.ru/scripts/XML_dynamic.asp?date_req1='.$curDate2.'&date_req2='.$curDate.'&VAL_NM_RQ=R01235'); // убираем переносы строк $currencyXML = str_replace(Array("\r\n","\n","\r"),'',$currencyXML); // регулярное выражение получает все значения тегов <Value> в массив $arValues preg_match_all('#<Value>(.*?)</Value>#', $currencyXML, $arValues, PREG_PATTERN_ORDER); // если совпадений больше одного, т.е. в xml были данные как минимум за 2 дня и можно отследить динамику if(count($arValues[1])>=2) { // развернем массив, чтобы первыми шли свежие данные $arValues[1] = array_reverse($arValues[1]); // сделаем резделителем целой и дробной части точку $kurs = str_replace(",",".",$arValues[1][0]); // разница курсов, округленная до 4х знаков после запятой $diff = round(floatval(str_replace(",",".",$arValues[1][0])) - floatval(str_replace(",",".",$arValues[1][1])), 4); }
«Завтра» и «несколько дней назад» выбраны не просто так — курс валюты иногда появляется заранее, а иногда не появляется вообще, например по воскресеньям или праздникам.
Теперь можно вывести в нужном месте значения переменных $kurs и $diff и радоваться полученному результату:)
Но дергать xml на каждом хите пользователя нехорошо, поэтому все это дело нужно закешировать
Кешируем результат в 1с-Битрикс
Кешировать будем результирующий html-код, для этого используем класс CPageCache.
<?if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die(); // создаем объект $obCache = new CPageCache; // время кеширования - 6 часов $life_time = 60*60*6; // формируем идентификатор кеша в зависимости от всех параметров // которые могут повлиять на результирующий HTML $cache_id = "iammegacachhhhhhhhhhhe"; // инициализируем буферизирование вывода if($obCache->StartDataCache($life_time, $cache_id, "/")): // формируем 2 даты - "завтра" и несколько дней назад $curDate = date('d/m/Y', mktime(0,0,0,date("n"),date("j")+1,date("Y"))); $curDate2 = date('d/m/Y', mktime(0,0,0,date("n"),date("j")-10,date("Y"))); // xml с сайта ЦБ РФ $currencyXML = file_get_contents('http://www.cbr.ru/scripts/XML_dynamic.asp?date_req1='.$curDate2.'&date_req2='.$curDate.'&VAL_NM_RQ=R01235'); // убираем переносы строк $currencyXML = str_replace(Array("\r\n","\n","\r"),'',$currencyXML); // регулярное выражение получает все значения тегов <Value> в массив $arValues preg_match_all('#<Value>(.*?)</Value>#', $currencyXML, $arValues, PREG_PATTERN_ORDER); // если совпадений больше одного, т.е. в xml были данные как минимум за 2 дня и можно отследить динамику if(count($arValues[1])>=2) { // развернем массив, чтобы первыми шли свежие данные $arValues[1] = array_reverse($arValues[1]); // сделаем резделителем целой и дробной части точку $kurs = str_replace(",",".",$arValues[1][0]); // разница курсов, округленная до 4х знаков после запятой $diff = round(floatval(str_replace(",",".",$arValues[1][0])) - floatval(str_replace(",",".",$arValues[1][1])), 4); } else { $kurs = ""; $diff = ""; }?> USD: <?=$kurs?><br /> Изменение: <?=$diff?> <? // записываем предварительно буферизированный вывод в файл кеша $obCache->EndDataCache(); endif; ?>
Пара слов о выборе времени кеширования и идентификатора кеша. Так как на всех страницах сайта результат работы скрипта одинаковый, то есть смысл оставить идентификатором константу, тогда будет один периодически обновляемый (6 часов в примере) файл кеша. Также можно привязать идентификатор к дате и увеличить время жизни кеша, тогда новые данные будут тянуться ровно 1 раз в сутки, но на каждый день появится отдельный файл.
Это не единственный способ получить данные о курсах валют и направлен, в первую очередь, на определение динамики их изменения. Если нужны только текущие значения, то логичнее его парсить из xml-файла http://www.cbr.ru/scripts/XML_daily.asp, который содержит сразу все валюты.
Больше статей и материалов по web-разработке в tg-канале - подписывайтесь!
Подписаться в telegram
Еще можно перед $obCache->EndDataCache(); вставить такое:
if(CModule::IncludeModule(«currency»))
{
$arFields = array(
«RATE» => floatval($kurs),
«RATE_CNT» => 1,
«CURRENCY» => «USD»,
«DATE_RATE» => $curDate,
);
$arFilter = array(
«CURRENCY» => «USD»,
«DATE» => $curDate,
);
$by = «date»;
$order = «desc»;
$db_rate = CCurrencyRates::GetList($by, $order, $arFilter);
if($ar_rate = $db_rate->Fetch())
{
if (!CCurrencyRates::Update($ar_rate[«ID»], $arFields))
echo «<div class=’errortext’>Ошибка обновления курса</div>»;
}
else
{
if (!CCurrencyRates::Add($arFields))
echo «<div class=’errortext’>Ошибка добавления курса</div>»;
}
}
else echo «<div class=’errortext’>Ошибка подключения модуля валют.</div>»;
Тогда курс будет сохранятся в Настройки->Валюты->Курсы Валют и использоваться при конвертации валют при оформлении заказов на сайте, и срабатывать в соответствии с кэшированием. Хотя, по хорошему нужно это в компонент оформить.
А вот, еще нашел более продвинутый вариант — http://dev.1c-bitrix.ru/community/webdev/user/3420/blog/653/ .
Это не очень круто — прег-матчить файл, почему бы не использовать simplexml например?