Получение курсов валют — задача, которая встречается очень часто. Курсы могут понадобиться чтобы просто показать их на веб-странице. Другой не менее распространённый случай — необходимость пересчитать цену в разных валютах. Какой бы ни была цель, важно чтобы курсы были получены из надёжного источника. Не менее важна их актуальность.
Самый надёжный и актуальный источник курсов валют — сайт Центробанка РФ. Через него можно получить доступ к XML-документу с курсами. Для этого нужно обратиться по URL ‘http://www.cbr.ru/scripts/XML_daily.asp’. В документе будет курсы валют на текущую дату. Также можно добавить к адресу параметр date_req, который позволяет явно указать дату, на которую нужны курсы. Тогда URL будет выглядеть следующим образом: ‘http://www.cbr.ru/scripts/XML_daily.asp?date_req=d.m.Y’. d.m.Y — это формат даты: день.месяц.год.
Кстати, PHP прекрасно понимает такие форматы дат.
XML-документ с курсами валют имеет следующую структуру: внутри корневого элемента находятся тэги <Valute>. Внутри каждого такого тэга находятся тэги, содержащие информацию о конкретной валюте. Для примера приведу скриншот XML-документа:

Тэгов внутри каждого элемента <Valute> довольно много, но чаще всего нужны 2 — <CharCode> и <Value>. С первым всё понятно, а второй — это курс валюты к рублю.
Таким образом, чтобы получить нужную нам информацию, надо сначала получить из PHP доступ к корневому XML-элементу, а потом перебрать все вложенные в него элементы <Valute>. Для каждого из них нужно просмотреть содержимое тех тэгов, которые описывают нужные нам свойства валюты.
Получить доступ ко вложенным XML-элементам из PHP совсем не сложно. Элементы можно получить по названию тэга с помощью функции getElementsByTagName(). Она возвращает коллекцию подходящих элементов. Для элементов <Valute> надо просто перебрать эту коллекцию в цикле, как уже говорилось выше. Когда мы ищем элементы, хранящие свойтва наподобие <CharCode>, внутри элемента <Valute>, функция getElementsByTagName() вернёт коллекцию из одного элемента. К нему можно обратиться следущим образом: item(0). Текст внутри тегов XML-элемента хранит свойство объекта nodeValue.
Теперь рассмотрим код примера на PHP:
<html> <?php //Xml-документ с курсами валют к рублю с сайта ЦБ РФ $xml = new DOMDocument(); $url = 'http://www.cbr.ru/scripts/XML_daily.asp?date_req=' . date('d.m.Y'); //Пробуем скопировать xml-документ с курсами валют с сайта ЦБ РФ на наш сервер $local_exchange_rates = "exchange_rates.xml"; @copy($url, $local_exchange_rates); //Поддерживаемые валюты и их курс к рублю $supported_currencies = ['USD' => NULL, 'EUR' => NULL]; //Загружаем xml-документ с курсами $is_loaded = false; if (@$xml->load($url)) $is_loaded = true; elseif (@$xml->load($local_exchange_rates)) $is_loaded = true; //Обновляем курсы поддерживаемых валют if ($is_loaded) { $root = $xml->documentElement; $currencies = $root->getElementsByTagName('Valute'); foreach ($currencies as $currency) { $char_code = $currency->getElementsByTagName('CharCode')->item(0)->nodeValue; if (array_key_exists($char_code, $supported_currencies)) { $value = $currency->getElementsByTagName('Value')->item(0)->nodeValue; $supported_currencies[$char_code] = floatval(str_replace(',', '.', $value)); } } foreach ($supported_currencies as $key => $value) { echo $key.' '.$value.'<br>'; } } else echo "Не удалось загрузить курсы валют"; ?> </html>
Стоит обратить внимание на 2 вещи:
- Мы выводим курсы только для тех валют, которые отметили как поддерживаемые. Для этого мы объявили массив $supported_currencies и поместили туда буквенные коды тех валют, которые хотим отслеживать.
- При каждом обращении к сайту ЦБ РФ мы сохраняем копию XML-документа локально. Если при следующем обращении к сайту ЦБ РФ он будет недоступен, то мы возьмём данные из локальной копии.
Рисунок 2 Эта система очень проста, но далеко не идеальна. Если предыдущее обращение было давно, то пользователь получит неактуальные курсы валют. Более сложный, но и более надёжный способ — вынести код создания локальной копии в отдельную программу и запускать эту программу как задание с определённой периодичностью. Но в этом посте мы не будем рассматривать как это сделать.
Спасибо за информацию.
Информация очень интересная
Thanks for sharing, this is a fantastic blog. Much thanks again. Anya Boris Jessica
Very energetic blog, I enjoyed that bit. Will there be a part
2?