Получение курсов валют с сайта Центробанка

Валюты

При разработке интернет-магазинов или различных информеров для сайтов часто приходится реализовывать получение актуальных курсов валют. Не все разработчики знают, что достаточно удобно получать курсы на любую дату используя API сайта Центрального банка РФ.

Курсы на сутки вперёд доступны в формате XML по адресу

http://www.cbr.ru/scripts/XML_daily.asp

Для получения данных на любую прошедшую дату нужно воспользоваться параметром date_req

http://www.cbr.ru/scripts/XML_daily.asp?date_req=12.07.2012

Теперь на нашем сайте нам достаточно распарсить XML файл и выбрать нужные валюты. Для выбора элементов из дерева можно использовать DOM или другие расширения для работы с XML.

Напишем класс, загружающий данные о курсах валют:

/**
 * @author ElisDN <mail@elisdn.ru>
 * @link http://www.elisdn.ru
 */
class CBRAgent
{
    protected $list = array();
 
    public function load()
    {
        $xml = new DOMDocument();
        $url = 'http://www.cbr.ru/scripts/XML_daily.asp?date_req=' . date('d.m.Y');
 
        if (@$xml->load($url))
        {
            $this->list = array(); 
 
            $root = $xml->documentElement;
            $items = $root->getElementsByTagName('Valute');
 
            foreach ($items as $item)
            {
                $code = $item->getElementsByTagName('CharCode')->item(0)->nodeValue;
                $curs = $item->getElementsByTagName('Value')->item(0)->nodeValue;
                $this->list[$code] = floatval(str_replace(',', '.', $curs));
            }
 
            return true;
        } 
        else
            return false;
    }
 
    public function get($cur)
    {
        return isset($this->list[$cur]) ? $this->list[$cur] : 0;
    }
}

Теперь мы можем загружать и считывать значения курса любой валюты относительно рубля:

$cbr = new CBRAgent();
if ($cbr->load()){    
    $usd_curs = $cbr->get('USD');
}

Обновление курсов нескольких валют в Yii Framework может, например, выглядеть так:

public function updateCurrencies()
{
    $cbr = new CBRAgent();
    if ($cbr->load())
    {    
        $models = Currency::model()->findAll()
        foreach ($models as $model)
        {                
            $model->curs = $cbr->get($model->name);
            $model->save();
        }  
    }
}

или так:

public function updateCurrencies()
{
    $cbr = new CBRAgent();
    if ($cbr->load())
    {    
        $currencies = array('USD', 'EUR');
 
        foreach($currencies as $currency)
        {                    
            Yii::app()->config->set('SHOP.CURS_' . $currency, $cbr->get($currency));
        }    
    }
}

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

Этот метод можно поместить в контроллер магазина и вызывать по таймауту или поместить в консольную команду и вызывать по Cron.

Другие статьи

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

Любой программист с опытом осознаёт, что в неудачно спроектированном тяжёлом проекте изначально или со временем накапливается много неуправляемого и ненужного мусора. Это, например, повторяющийся код. В описании контроллера официального руководства Yii Framework указано, что Yii поддерживает вынос действий в отдельные классы и описывается процедура подключения этих действий к контроллерам. Но мало кто пользуется этим способом, так как не находит действительно тяжёлых повторяющихся экшенов.

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

Как многим известно, для хранения настроек приложения в Yii выделен специальный раздел `params` в конфигурационном файле. Это решение достаточно простое, но оно не позволяет легко менять настройки самому пользователю в панели управления сайта. Очередной вопрос на русском форуме Yii натолкнул меня поделиться своим вариантом решения упомянутого там вопроса.

Комментарии

 

Виталий

Не могу понять, какого хрена http://www.cbr.ru/scripts/XML_daily.asp возвращает контент 1 раз из 20-и... Пробовал через file_get_contents, через curl, через сокеты, теперь вот напрямую с помощью DOMDocument...

Через браузер вроде все ок. Иногда сбрасываются соединения, но не так безбожно.

Это руки у меня кривые или это фаервол такой?

Ответить

 

Дмитрий Елисеев

Тоже не открывается. Значит админы уже Новый Год празднуют.

Ответить

 

Андрей

Подскажите как выдернуть дату из ответа <valcurs date="10.04.2014" name="Foreign Currency Market" />

Ответить

 

Дмитрий Елисеев
$valcurs = $root->getElementsByTagName('valcurs');
echo $valcurs[0]->getAttribute('date');
Ответить

 

Андрей

Спасибо, но

Fatal error: Call to undefined method DOMNodeList::getAttribute()

не работает(

Еще замечено, что очень часто попытка загрузки через php url http://www.cbr.ru/scripts/XML_daily.asp выводит пустой ответ, на локалке лечится открытием этого урла в браузере, на хостинге - урла через wget.
Как побороть кто знает? Curl?

Ответить

 

Дмитрий Елисеев

Тогда можно попробовать что-то вроде:

echo $valcurs->item(0)->getAttribute('date');

В общем, выцепить из массива первый элемент.

Ответить

 

Akej

а как запустить контроллер по таймауту??

Ответить

 

Akej

Вернее запустить метод контроллера по таймауту?

Ответить

 

Дмитрий Елисеев

Оформить как консольную команду и настроить её запуск по Cron (должен быть в панели управления хостинга) как здесь.

Ответить

 

Дмитрий

от 06.11.2014

class CBRAgent{
	protected $list = array();
 
	public function load(){
		$url = 'http://www.cbr.ru/scripts/XML_daily.asp?date_req='.date('d.m.Y', time());
		$xml = simplexml_load_file($url);
	
		if($xml){
			foreach ($xml as $item){
				$code = strval($item->CharCode);
				$curs = $item->Value;
				$this->list[$code] = floatval(str_replace(',', '.', $curs));
			}
			return true;
		}else{
			return false;
		}
	}
 
	public function get($cur){
		return isset($this->list[$cur]) ? $this->list[$cur] : 0;
	}
}

$cbr = new CBRAgent();
if ($cbr->load()){    
	$usd_curs = $cbr->get('USD');
}
Ответить

 

Евгений

простое кэширование на диске(public_html) раз в день по запросу без всяких кронов

class CBRAgent
{
    protected $list = array();
    public function load()
    {
        $xml = new \DOMDocument();
        $filepath = 'curs_valute_'.date('d.m.Y').'.xml';
        if(file_exists($filepath)){
            $tosave = false;
            $path = $filepath;
        } else {
            $tosave = true;
            $path = 'http://www.cbr.ru/scripts/XML_daily.asp?date_req=' . date('d.m.Y');
        }
        if (@$xml->load($path))
        {
            if($tosave){
                array_map('unlink', glob('curs_valute_*.xml'));
                @$xml->save($filepath);
            }
            $this->list = array();
            $root = $xml->documentElement;
            $items = $root->getElementsByTagName('Valute');
            foreach ($items as $item)
            {
                $code = $item->getElementsByTagName('CharCode')->item(0)->nodeValue;
                $curs = $item->getElementsByTagName('Value')->item(0)->nodeValue;
                $this->list[$code] = floatval(str_replace(',', '.', $curs));
            }
            return true;
        }
        else
            return false;
    }

    public function get($cur)
    {
        return isset($this->list[$cur]) ? $this->list[$cur] : 0;
    }
}
Ответить

 

Влад

Добрый день Дмитрий. Помогите создать 2 информера курса валют: евро и доллара. Я далек от программирования. Буду признателен.

Ответить

 

Дмитрий Елисеев

Скопируйте себе HTML-код готовых вроде этих.

Ответить

 

kursvaliut

kursvaliut.ru позволяет взять бесплатный ежедневный обновленный курс валют ЦБ или в том числе конвертер валют включив простой JavaScript :)

Ответить

Оставить комментарий

Войти | Завести аккаунт


(никто не увидит)



Можно использовать теги <p> <ul> <li> <b> <i> <a> <pre>