Артём Мáлков

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

25 сен77 комм

В некоторых случаях при работе с коммерцией возникает необходимость получения актуальной информации о курсе той или иной валюты. Центробанк – лучший источник таких данных, а учитывая то, что он предоставляет открытую и своевременно обновляемую информацию о курсе валют в формате XML – грех ею не воспользоваться.

Я рад поделиться с вами своей небольшой функцией, которая отлично справляется с описанной в заголовке задачей, а именно – бесплатным получением курса валют ЦБ РФ на PHP.

Функция эта выглядит следующим образом:

function get_currency($currency_code, $format) {

	$date = date('d/m/Y'); // Текущая дата
	$cache_time_out = 14400; // Время жизни кэша в секундах

	$file_currency_cache = './currency.xml'; // Файл кэша

	if(!is_file($file_currency_cache) || filemtime($file_currency_cache) < (time() - $cache_time_out)) {

		$ch = curl_init();

		curl_setopt($ch, CURLOPT_URL, 'https://www.cbr.ru/scripts/XML_daily.asp?date_req='.$date);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
		curl_setopt($ch, CURLOPT_HEADER, 0);

		$out = curl_exec($ch);

		curl_close($ch);

		file_put_contents($file_currency_cache, $out);

	}

	$content_currency = simplexml_load_file($file_currency_cache);

	return number_format(str_replace(',', '.', $content_currency->xpath('Valute[CharCode="'.$currency_code.'"]')[0]->Value), $format);

}

В ней строки:

$date = date('d/m/Y'); // Текущая дата
$cache_time_out = 14400; // Время жизни кэша в секундах

отвечают за дату (в нашем случае она текущая) и время жизни кэша соответственно. Поскольку ЦБ не так часто обновляет данные о валютах, не стоит докучать ему просто так при каждом их использовании. Значения в этих строках (по желанию) можете изменить на свои.

Использование функции следующее:

echo get_currency('USD', 3);

Здесь «USD» – символьный код валюты (в нашем случае – это доллар США), а «3» – количество знаков после запятой.

Допустимый перечень валют, предоставляемых ЦБ РФ (на момент написания статьи) в виде «символьный код валюты – номинал и название»:

AUD – 1 австралийский доллар
AZN – 1 азербайджанский манат
GBP – 1 фунт стерлингов Соединенного королевства
AMD – 100 армянских драмов
BYN – 1 белорусский рубль
BGN – 1 болгарский лев
BRL – 1 бразильский реал
HUF – 100 венгерских форинтов
HKD – 10 гонконгских долларов
DKK – 10 датских крон
USD – 1 доллар США
EUR – 1 евро
INR – 100 индийских рупий
KZT – 100 казахстанских тенге
CAD – 1 канадский доллар
KGS – 100 киргизских сомов
CNY – 10 китайских юаней
MDL – 10 молдавских леев
NOK – 10 норвежских крон
PLN – 1 польский злотый
RON – 1 румынский лей
XDR – 1 СДР (специальные права заимствования)
SGD – 1 сингапурский доллар
TJS – 10 таджикских сомони
TRY – 1 турецкая лира
TMT – 1 новый туркменский манат
UZS – 10 000 узбекских сумов
UAH – 10 украинских гривен
CZK – 10 чешских крон
SEK - 10 шведских крон
CHF – 1 швейцарский франк
ZAR – 10 южноафриканских рэндов
KRW – 1 000 вон Республики Корея

Надеюсь, функция найдет свое место в вашем проекте. Если остались вопросы или что-то показалось непонятным – обязательно пишите об этом в комментариях под данной статьей.

Рекомендуем к просмотру
Информер общей мировой статистики заражений коронавирусом COVID-19 (2019-nCoV)
Модули и скрипты
Получаем статистику заражений коронавирусом COVID-19 (2019-nCoV) на PHP+API
Модули и скрипты
Получаем курсы валют с сайта Национального банка Казахстана на PHP
Модули и скрипты
77
комментариев
Форма комментирования этого поста скрыта. Авторизуйтесь, чтобы расширить привилегии гостевого посещения и получить необходимую помощь от сообщества Pandoge.
    • 1
    41
      •  Проверенный
    2 авг в 00:29

    Здравствуйте, Артём.

    Не нашел отдельную форму для добавления идеи.

    Если будет у вас время, сделайте конвертер валют на основе данных ЦБ РФ.

    Чтобы калькулятор умел конвертировать рубль на доллары, доллары на рубли, рубли на евро, евро на рубли. Вот пример https://ilyamio.github.io/currencyconverter/ Но этот конвертер валют работает не на основе данных из cbr.ru, а другого англоязычного сервиса.

      • 1
      1066
        •  Команда Pandoge
      2 авг в 09:19

      Илья, здравствуйте!

      Я думал об этом, где бы время только найти...

    • 1
    41
      •  Проверенный
    10 июл в 01:19

    Здравствуйте! Возможно ли также отображать и историю изменения курсов валют? Например, как в этом примере https://skr.sh/vEqEtxWmDTO?a (видео скриншот)

      • 1
      1066
        •  Команда Pandoge
      10 июл в 13:01

      Илья, здравствуйте!

      Учитывая, что ЦБ предоставляет курс валют за разные даты - да, такое можно сделать.

      • 1
      41
        •  Проверенный
      10 июл в 17:11

      Артём Мáлков, добрый день! Можете поделиться информацией как это реализовать?

      • 1
      1066
        •  Команда Pandoge
      11 июл в 01:31

      Илья, банальный ответ - писать код.

      А так, что уже пробовали и что из этого не получилось?

      • 1
      41
        •  Проверенный
      11 июл в 20:58

      Артём Мáлков, здравствуйте.

      Я еще не пробовал, так как не знаю как это реализовать. Поэтому и написал тут.

      • 1
      1066
        •  Команда Pandoge
      12 июл в 09:31

      Илья, здравствуйте!

      Подумаю и на днях дам ответ.

      • 2
      1066
        •  Команда Pandoge
      14 июл в 12:04

      Илья, здравствуйте! Есть некоторые мысли, будем разбираться вместе в нескольких комментариях (в несколько дней, немного занят).

      У ЦБ есть своя документация по получению курса валют. Находится она здесь - http://www.cbr.ru/development/sxml/

      Если внимательно её посмотреть, то можно найти пример, с помощью которого дают возможность получить курс валют за определенный диапазон дат, а это то, что нам нужно:

      http://www.cbr.ru/scripts/XML_dynamic.asp?date_req1=02/03/2001&date_req2=14/03/2001&VAL_NM_RQ=R01235

      Здесь R01235 - это ID USD, 02/03/2001 и 14/03/2001 - дата начала и конца выборки соответственно.

      Что нас здесь смущает?

      Пока ничего, но если мы начнём писать скрипт под вашу задачу, то дата, поскольку здесь она статичная (неизменяемая), а нам нужна динамичная (изменяемая), чтобы мы, например, могли получить актуальный курс валют за последнюю неделю (7 дней).

      Решаем вопрос с датой. На PHP (именно на нём мы будем писать наш код) текущую дату можно получить следующим образом:

      echo date('d/m/Y');

      Чтобы получить другую дату относительно этой (в нашем случае, дату на 7 дней назад), нужно воспользоваться следующей конструкцией:

      echo date('d/m/Y', strtotime('-7 days'));

      Проверяем, если дата выводится в обоих случаях та, которую мы ожидаем, то мы решили первую часть задачи и получили ссылку на курс валют с ежедневным смещением дат:

      echo 'http://www.cbr.ru/scripts/XML_dynamic.asp?date_req1='.date('d/m/Y', strtotime('-1 days')).'&date_req2='.date('d/m/Y').'&VAL_NM_RQ=R01235';

      Эта часть понятна?

      • 2
      41
        •  Проверенный
      15 июл в 02:19

      Артём Мáлков, здравствуйте!

      Да, эта часть понятна.

      Спасибо, что решились помочь с этой задачей!

      • 2
      1066
        •  Команда Pandoge
      15 июл в 22:42

      Илья, итак, идём дальше.

      Если посетить полученную ссылку (а это мы должны были сделать ещё в самом начале) в браузере, то можно увидеть, что там нам доступен курс валюты (одной) за несколько дней.

      Отлично, значит мы имеем необходимые данные и следующая наша задача - это получить их, непосредственно, не в браузере а в нашем скрипте, обработать, ну и, собственно, вывести.

      В этом посте приведена функция, получающая данные по ссылке. В целом, она подходит нам, но есть одно важное «но» - в ней мы получаем (и выводим) данные только за один день, а поскольку у нас этих дней возвращается несколько, но нам необходимо дополнительно произвести операцию по выводу всех их.

      Новая функция будет выглядеть следующим образом:

      function get_currency($currency_code = 'R01235') {
      
      	$date_start = date('d/m/Y', strtotime('-7 days')); // Дата начала выборки
      	$date = date('d/m/Y'); // Текущая дата (используется для кэша и для конца выборки)
      
      	$cache_time_out = 14400; // Время жизни кэша в секундах
      
      	$file_currency_cache = './currency.xml'; // Файл кэша
      
      	if(!is_file($file_currency_cache) || filemtime($file_currency_cache) < (time() - $cache_time_out)) {
      
      		$ch = curl_init();
      
      		curl_setopt($ch, CURLOPT_URL, 'https://www.cbr.ru/scripts/XML_dynamic.asp?date_req1='.$date_start.'&date_req2='.$date.'&VAL_NM_RQ='.$currency_code);
      		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
      		curl_setopt($ch, CURLOPT_HEADER, 0);
      
      		$out = curl_exec($ch);
      
      		curl_close($ch);
      
      		file_put_contents($file_currency_cache, $out);
      
      	}
      
      	$content_currency = simplexml_load_file($file_currency_cache);
      
      	$content_currency_result = ''; // Переменная для объединения всех дней в одну группу
      
      	foreach($content_currency->Record as $currency) {
      
      		$content_currency_result .= $currency->attributes()->Date.' - '.$currency->Value.'<br />';
      
      	}
      
      	return $content_currency_result;
      
      }

      Её использование (вывод):

      echo get_currency('R01235');

      Здесь R01235, напомню, - это ID USD. Список ID всех доступных валют вы найдете здесь - http://www.cbr.ru/scripts/XML_val.asp?d=0

      Что у вас получилось и всё ли понятно по этой части?

      • 1
      41
        •  Проверенный
      16 июл в 15:21

      Артём Мáлков, добрый день!

      Да, все понятно. Протестировал у себя. Вот результат https://skr.sh/sExTiaIzA3G?a

      Круто получается все!

      • 2
      41
        •  Проверенный
      17 июл в 23:01

      Артём, здравствуйте. А продолжение будет? Спасибо!

      • 1
      1066
        •  Команда Pandoge
      18 июл в 01:41

      Илья, да, сегодня постараюсь прислать

      • 2
      1066
        •  Команда Pandoge
      18 июл в 22:45

      Илья, поскольку мы успешно получили данные, следующая (и завершающая) часть - это их визуализация.

      Для этих целей, я думаю, есть множество инструментов, мне же из них знаком Highcharts. Официальный сайт - https://www.highcharts.com. Не вдаваясь в сильные подробности (хотя в коде я дам некоторые комментарии), приведу пример простого использования, подходящего под вашу задачу:

      <div id="highcharts"></div>
      
      <script src="https://code.highcharts.com/highcharts.js"></script>
      
      <script>
      	Highcharts.chart("highcharts", {
      		colors: ["#000"], // Цвет элементов графика (линии и точек)
      		chart: {
      			type: "areaspline" // Тип линии
      		},
      		plotOptions: {
      			areaspline: {
      				fillOpacity: 0 // Прозрачность линии
      			}
      		},
      		title: {
      			text: "" // Название графика
      		},
      		xAxis: {
      			title: {
      				text: "" // Название оси X
      			},
      			categories: [] // Массив значений по оси X
      		},
      		yAxis: {
      			title: {
      				text: "" // Название оси Y
      			}
      		},
      		series: [{
      			name: "", // Название значений
      			data: [] // Массив значений по оси Y
      		}],
      		tooltip: {
      			shared: true,
      			valueSuffix: "" // Окончание значений
      		},
      		accessibility: {
      		  enabled: false
      		}
      	});
      </script>

      Всё, что нам остается сделать - это динамически подставлять сюда (в скрипт) получаемые данные от ЦБ. В следующем комментарии я покажу, как именно это можно сделать. А вы пока рассмотрите пример выше.

      • 1
      41
        •  Проверенный
      19 июл в 00:22

      Артём, здравствуйте! Спасибо большое! Буду с нетерпением ждать!

      • 1
      1066
        •  Команда Pandoge
      19 июл в 09:10

      Илья, скрипт выше поразбирали?

      • 1
      41
        •  Проверенный
      20 июл в 12:14

      Артём, добрый день!

      Да, до комментария об использовании Highcharts, я все понял.

      • 1
      1066
        •  Команда Pandoge
      изменено 20 июл в 14:16

      Илья, здравствуйте!

      Вопрос именно про Highcharts, посмотреть как он работает со статичными данными

      • 1
      41
        •  Проверенный
      21 июл в 00:19

      Артём здравствуйте.

      Думаю, что смогу разобраться если данные статичные. Но вот подставлять динамические данные в js скрипт Highcharts будет сложно, если не знать как это сделать.

      Пока не представляю как это можно динамически подставлять данные в хайчатс.

      • 1
      1066
        •  Команда Pandoge
      21 июл в 09:57

      > Думаю, что смогу разобраться если данные статичные.

      В этом и вопрос, что пробовали сейчас разобраться со статикой или нет на основе присланного кода?

      Мне больше интереснее научить вас, чем просто выложить готовое решение.

      • 1
      41
        •  Проверенный
      21 июл в 18:56

      Артём, добрый вечер!

      Как я понял, данные нужно вводить в series.

      Я пробовал. Но не удается указать даты. А только значения курсов.

      Если дублировать series для каждой даты: [{

      name: '21.07.2022',

      data: [43.934, 52.503, 57.177, 69.658, 9.7031, 11.9931, 37б13, 54.175]

      },

      name: '22.07.2022',

      data: [43.934, 52.503, 57.177, 69.658, 9.7031, 11.9931, 37б13, 54.175]

      },

      то появляется много линий. Вот так https://skr.sh/sF2h8k6yc9q?a

      Пока изучаю документацию. Надеюсь найду ответ как в одной линии добавить и даты и курсы.

      • 2
      1066
        •  Команда Pandoge
      21 июл в 22:13

      Илья, добрый вечер!

      Каждый series - это новая линия. Это лучше использовать для разных валют, а для одной вы заполняете в:

      categories: [] // Массив значений по оси X

      как раз таки ваши даты, а в:

      data: [] // Массив значений по оси Y

      курс валюты для соответствующей даты

      • 1
      41
        •  Проверенный
      23 июл в 03:45

      Артём, здравствуйте.

      Вот так правильно? :

      <div id="highcharts"></div>
      
      <script src="https://code.highcharts.com/highcharts.js"></script>
      
      <script>
      	Highcharts.chart("highcharts", {
      
      colors: ["#000"], // Цвет элементов графика (линии и точек)
      
      chart: {
      
      type: "areaspline" // Тип линии
      
      },
      
      plotOptions: {
      
      areaspline: {
      
      fillOpacity: 0 // Прозрачность линии
      
      }
      
      },
      
      title: {
      
      text: "" // Название графика
      
      },
      
      xAxis: {
      
      categories: ['12.07.2022', '13.07.2022', '14.07.2022', '15.07.2022', '16.07.2022', '17.07.2022', '18.07.2022', '19.07.2022', '20.07.2022', '21.07.2022', '22.07.2022', '23.07.2022']
      
      },
      
      yAxis: {
      
      title: {
      
      text: 'Temperature (°C)'
      
      }
      
      },
      
      series: [{
      
      name: 'USD currency history',
      
      data: [54.24, 69.45, 55.43, 54.54, 58.34, 52.54, 54.25, 56.54, 53.53, 58.53, 53.95, 59.26]
      
      }],
      
      tooltip: {
      
      shared: true,
      
      valueSuffix: "" // Окончание значений
      
      },
      
      accessibility: {
      
      enabled: false
      
      }
      	});
      </script>

      Вот скриншот https://skr.sh/sF48b1dBvs5?a

      Возникла одна проблема. Курсы валют перестали отображаться. Ранее все отображалось, но сейчас уже ничего не выводит https://skr.sh/vF41BtfhI9o?a

      • 1
      41
        •  Проверенный
      23 июл в 16:33

      Добрый день, Артём.

      В предыдущем комментарии, я писал, что курсы валют перестали отображаться.

      Думаю, что это из-за того, что на сайте цб есть проверка на ботов с помощью cloudfare. Поэтому наверно ничего не отображается.

      По-моему, мы с помощью кода не сможем обойти проверку cloudfare?

      • 1
      1066
        •  Команда Pandoge
      23 июл в 23:07

      Илья, по коду - всё верно. По тому, что не отображается валюта - очень возможно. У меня один раз такое повторялось, но я не искал решения.

      Думаю, что стоит увеличить время кэша и обновлять файл раз в день.

      • 1
      41
        •  Проверенный
      24 июл в 13:29

      Артём, добрый день! Время кэша указал 86400 в php коде. И с статичными данными highcharts вроде разобрался. https://skr.sh/vF5R4oOUTOL?a

      Хотел пойти дальше, но остановился на вопросе, как же теперь разделить даты и значения курсов и эти данные указать в categories; [] и data; [] чтобы это все работало динамически.

      • 1
      41
        •  Проверенный
      24 июл в 15:14

      Артём, добрый день!

      Как можно сделать так чтобы файл каждый 1 раз скачивался из cbr и данные выводились из этого файла? Я думал, что после изменения времени в кэше, ошибка не повторится. Но ошибка повторилась. В ошибках есть запись "DDoS protection by DDoS-GUARD". Поэтому подумал, может так сделать, чтобы надежно было. Спасибо.

      • 1
      41
        •  Проверенный
      30 июл в 17:02

      Артём, добрый день! Еще я обратил внимание на то, что значения курсов из cbr загружаются через запятую. Пример: 52,9699. А в highcharts в data: [] эти значения невозможно указать как есть, только с помощью точки. Пример, 52.9699. Иначе не получится отобразить графику.

      • 1
      41
        •  Проверенный
      30 июл в 22:29

      Оказывается запятую можно изменить на току с помощью php:

      $dot = str_replace(',','.',$content_currency_result); //Меняем запятую на точку

      Но вопрос с распределением дат и курсов в highcharts остается не решенным. Пробовал разные варианты, но не получилось их разделить и в highcharts отобразить динамически.

      • 2
      1066
        •  Команда Pandoge
      изменено 30 июл в 22:34

      Илья, здравствуйте! Прошу прощения за поздний ответ.

      Первое, что вам необходимо сделать, это немного изменить функцию получения курса валют, а именно, часть:

      $content_currency_result = ''; // Переменная для объединения всех дней в одну группу
      
      foreach($content_currency->Record as $currency) {
      
      	$content_currency_result .= $currency->attributes()->Date.' - '.$currency->Value.'<br />';
      
      }

      заменить на:

      $content_currency_result = [];
      
      foreach($content_currency->Record as $currency) {
      
      	$content_currency_result[0][] = '"'.$currency->attributes()->Date.'"';
      	$content_currency_result[1][] = str_replace(',', '.', $currency->Value);
      
      }

      Это нужно для того, чтобы мы собрали в одной переменной отдельно группу дат и отдельно группу курса.

      Далее, сразу после объявления функции вызываем её:

      $currencyArr = get_currency('R01235');

      А после, как завершающий шаг, вставляем данные (группы) в соответствующие места Highcharts:

      Highcharts.chart("highcharts", {
      	colors: ["#000"], // Цвет элементов графика (линии и точек)
      	chart: {
      		type: "areaspline" // Тип линии
      	},
      	plotOptions: {
      		areaspline: {
      			fillOpacity: 0 // Прозрачность линии
      		}
      	},
      	title: {
      		text: "Динамика курса доллара США" // Название графика
      	},
      	xAxis: {
      		title: {
      			text: "" // Название оси X
      		},
      		categories: [<?php echo implode(', ', $currencyArr[0]); ?>] // Массив значений по оси X
      	},
      	yAxis: {
      		title: {
      			text: "" // Название оси Y
      		}
      	},
      	series: [{
      		name: "курс", // Название значений
      		data: [<?php echo implode(', ', $currencyArr[1]); ?>] // Массив значений по оси Y
      	}],
      	tooltip: {
      		shared: true,
      		valueSuffix: " ₽" // Окончание значений
      	},
      	accessibility: {
      	  enabled: false
      	}
      });
      • 1
      41
        •  Проверенный
      30 июл в 22:42

      Артём, здравствуйте!

      Гениально! Слов нет! Вот такой результат: https://skr.sh/sFBGanfjffO?a

      Большое вам спасибо, Артём!

      Но если вы не возражаете, могу ли я также задать несколько вопросов по теме курсов валют?

      • 1
      1066
        •  Команда Pandoge
      30 июл в 23:07

      Илья, пишите, по возможности отвечу

      • 1
      41
        •  Проверенный
      31 июл в 01:14

      Артём, весь код сохранил в сниппете usdhistory. Сайт работает на Modx Revo. Насколько знаю, вы и с Modx Revo тоже работаете.

      Потом вызвал сниппет [[usdhistory]] на необходимой странице. Все отлично работает.

      Единственно, после графы, то есть, под нее, отображается текст: return; 1.

      С чем это может быть связано? Как можно убрать это сообщение?

      • 1
      41
        •  Проверенный
      31 июл в 13:12

      Добрый день, Артём.

      На основе выше предложенного php кода, мне удалось также вывести курсы валют и в таблице.

      Вот и код:

      <?php
      function get_currency_td($currency_code = 'R01235') {
      
      $date_start = date('d/m/Y', strtotime('-30 days')); // Дата начала выборки
      	$date = date('d/m/Y'); // Текущая дата (используется для кэша и для конца выборки)
      
      $cache_time_out = 86400; // Время жизни кэша в секундах
      
      $file_currency_cache = './currency.xml'; // Файл кэша
      
      if(!is_file($file_currency_cache) || filemtime($file_currency_cache) < (time() - $cache_time_out)) {
      
      $ch = curl_init();
      
      curl_setopt($ch, CURLOPT_URL, 'https://www.cbr.ru/scripts/XML_dynamic.asp?date_req1='.$date_start.'&date_req2='.$date.'&VAL_NM_RQ='.$currency_code);
      
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      
      curl_setopt($ch, CURLOPT_HEADER, 0);
      
      $out = curl_exec($ch);
      
      curl_close($ch);
      
      file_put_contents($file_currency_cache, $out);
      
      }
      
      $content_currency = simplexml_load_file($file_currency_cache);
      
      $content_currency_result = ''; // Переменная для объединения всех дней в одну группу
      
      foreach($content_currency->Record as $currency) {
      
      $content_currency_result .= '<tr><td>'.$currency->attributes()->Date.' </td><td> '.$currency->Value.'</td><td></td></tr>';
      
      }
      
      return $content_currency_result;
      
      }
      
      ?>
      <div class="currency-exchange">
      
      <div class="ce-title">Таблица изменений курса доллара США за 30 дней</div>
      
      <table class="table table-condensed ce-table">
      
      <thead>
      
      <tr>
      
      <td>Дата</td>
      
      <td>Курс рублей за 1 usd</td>
      
      <td>Изменение</td>
      
      </tr>
      
      </thead>
      
      <tbody>
      
      <? echo get_currency_td('R01235'); ?>
      
      </tbody>
      
      </table>
      </div>

      Цель - в 3-ем td вывести разницу курса в зеленом и красных цветах в зависимости от изменения курса в лучшую сторону и наоборот.

      Есть также проблема в Modx Revo. Весь этот код я сделал сниппетом. После вызова данного сниппета, на странице под таблице отображается текст: return; 1. Не знаю как бороться с этой ошибкой.

      • 1
      1066
        •  Команда Pandoge
      изменено 31 июл в 20:36

      Илья, поскольку ранее описанная мной функция содержит в себе даты и курс валюты, таблицу сформировать можно на неё основе.

      Пример:

      $currency_tr = '';
      
      for($i = 0; $i < count($currencyArr[0]); $i++) {
      	
      	$currency_tr .= '
      	
      		<tr>
      			<td>'.$currencyArr[0][$i].'</td>
      			<td>'.$currencyArr[1][$i].'</td>
      			<td></td>
      		</tr>
      	
      	';
      	
      }

      В нужное место таблицы:

      <?php echo $currency_tr; ?>
      • 2
      41
        •  Проверенный
      31 июл в 20:39

      Оказывается в Modx Revo в сниппетах если смешивать php и html код, то могут возникать ошибки. Поэтому у меня выходила ошибка return; 1. В сниппете оставил только php, а html перенес в шаблон. Теперь ошибки return; 1 нет.

      • 1
      41
        •  Проверенный
      31 июл в 21:47

      Артём, добрый вечер!

      Данный php код:

      $content_currency_result = ''; // Переменная для объединения всех дней в одну группу
      
      foreach($content_currency->Record as $currency) {
      
      $content_currency_result .= '<tr><td>'.$currency->attributes()->Date.' </td><td> '.$currency->Value.'</td><td></td></tr>';
      
      }

      заменить на следующий код ? :

      $currency_tr = '';
      
      for($i = 0; $i < count($currencyArr[0]); $i++) {
      	
      	$currency_tr .= '
      	
      		<tr>
      			<td>'.$currencyArr[0][$i].'</td>
      			<td>'.$currencyArr[1][$i].'</td>
      			<td></td>
      		</tr>
      	
      	';
      	
      }
      • 1
      41
        •  Проверенный
      31 июл в 22:18

      Артём,

      тут:

      $currency_tr = '';
      
      for($i = 0; $i < count($currencyArr[0]); $i++) {
      	
      	$currency_tr .= '
      	
      		<tr>
      			<td>'.$currencyArr[0][$i].'</td>
      			<td>'.$currencyArr[1][$i].'</td>
      			<td></td>
      		</tr>
      	
      	';
      	
      }

      где-то скорее всего есть опечатка или ошибка, так как ошибка выходит:

      Notice: Undefined variable: currency_tr in /home/ru/public_html/kursy/usd_tr.php on line 78
      • 1
      1066
        •  Команда Pandoge
      31 июл в 22:51

      Илья, предложенный код нужно вставить сразу после:

      $currencyArr = get_currency('R01235');

      Вашу функцию (всю) нужно удалить.

      • 1
      41
        •  Проверенный
      31 июл в 23:36

      Артём, так теперь все отлично работает.

      Но вот в Modx Revo таблица пустым отображается. Может у вас есть идеи как перенести в Modx Revo?

      Еще хотелось бы, в 3-ю td вывести разницу в курсе в зеленых и красных цветах.

      • 1
      1066
        •  Команда Pandoge
      1 авг в 10:22

      Илья, я не знаю как сейчас оформлен у вас код, но как рекомендация - и график и таблицу нужно поместить в один сниппет.

      На счёт разницы - подумаю на днях, напишу.

      • 2
      41
        •  Проверенный
      2 авг в 00:32

      Артём, здравствуйте. Проблему с пустой таблицей решил. Перенес в Modx Revo.

      Все отлично работает. Единственно, пришлось 2 сниппета сделать, объединить их в 1 сниппет не смог.

      • 1
      1066
        •  Команда Pandoge
      7 авг в 02:42

      Илья, здравствуйте!

      Насчёт этого:

      Еще хотелось бы, в 3-ю td вывести разницу в курсе в зеленых и красных цветах.

      В моём последнем коде (комментарий от 31 июл 20:36)

      $currency_tr .= '
      
      	<tr>
      		<td>'.$currencyArr[0][$i].'</td>
      		<td>'.$currencyArr[1][$i].'</td>
      		<td></td>
      	</tr>
      
      ';

      замените на:

      $td_3 = '';
      
      if(!is_null($currencyArr[1][$i - 1])) {
      
      	$td_3 = number_format(str_replace(',', '.', ($currencyArr[1][$i] - $currencyArr[1][$i - 1])), 4);
      
      	if($td_3 > 0) {
      
      		$td_3 = '<span style="color: green;">+'.$td_3.'</span>';
      
      	} elseif($td_3 < 0) {
      
      		$td_3 = '<span style="color: red;">'.$td_3.'</span>';
      
      	} else {
      
      		$td_3 = '<span style="color: black;">'.$td_3.'</span>';
      
      	}
      
      }
      
      $currency_tr .= '
      
      	<tr>
      		<td>'.$currencyArr[0][$i].'</td>
      		<td>'.$currencyArr[1][$i].'</td>
      		<td>'.$td_3.'</td>
      	</tr>
      
      ';

      Сразу о нюансе: у нас у первой строки нет значения в третьей ячейке, так как нет предыдущего дня. В таком случае, можно увеличить выборку ещё на один день, но первый день на экран не выводить.

      • 1
      41
        •  Проверенный
      7 авг в 21:23

      Артём, здравствуйте! Спасибо большое!

      Почему-то после замены, все значения отображаются пустыми. И отображается только один tr c 3-мя пустыми td.

      Вот так https://skr.sh/sFJ2cfQb3Fx?a

      • 0
      1066
        •  Команда Pandoge
      7 авг в 22:19

      Илья, нужно увидеть весь код, чтобы понять в чём дело.

      • 0
      41
        •  Проверенный
      7 авг в 22:44

      Артём, весь код тут https://drive.google.com/file/d/1fcEyGmk8gjZfe6g36useu52H1p_dWQ8J/view?usp=sharing

      • 0
      1066
        •  Команда Pandoge
      изменено 8 авг в 09:35

      Илья, сделали не инструкции. Ещё раз посмотрите мой комментарий и поймите, в чём ошибка.

      • 0
      41
        •  Проверенный
      8 авг в 21:20

      Артём, здравствуйте.

      Вот тут:

      $content_currency_result = [];
      
      foreach($content_currency->Record as $currency) {
      
      	$content_currency_result[0][] = '"'.$currency->attributes()->Date.'"';
      	$content_currency_result[1][] = str_replace(',', '.', $currency->Value);
      
      }

      заменил на:

      $content_currency_result = ''; // Переменная для объединения всех дней в одну группу
      
      foreach($content_currency->Record as $currency) {
      
      	$content_currency_result .= $currency->attributes()->Date.' - '.$currency->Value.'<br />';
      
      }

      Вот такой результат вышел: https://skr.sh/sFKrUrhBkX8?a

      Но думаю, что где-то все равно есть опечатка, так как курс не правильно показывает и только за 1 день, хотя в выборке указано 30 дней.

      • 0
      41
        •  Проверенный
      8 авг в 21:44

      Не нашел ошибку. Вроде все по инструкции сделал. Перечитал все комментарии и делал все по комментариям. И по несколько раз перепроверял не делаю ли ошибку. Нет, ошибок нет.

      • 1
      41
        •  Проверенный
      8 авг в 22:37

      Артём, ошибку нашел)

      Ошибка была тут:

      $currency_tr .= '
      	
      		<tr>
      			<td>'.$currencyArr[0][$i].'</td>
      			<td>'.$currencyArr[1][$i].'</td>
      			<td></td>
      		</tr>
      	
      	';
      	
      }

      Я оказывается удалил код:

      $currency_tr = '';
      
      for($i = 0; $i < count($currencyArr[0]); $i++) {

      Поэтому изменение курса по дням не работало у меня.

      Но, все же, есть такое сообщение:

      Notice: Undefined offset: -1 in /home/site.ru/public_html/kursy/usd-tr3.php on line 58
      • 0
      1066
        •  Команда Pandoge
      9 авг в 00:24

      Илья, всё верно smiley

      Что касается ошибки - нужно опять же видеть код, чтобы вам подсказать.

      • 0
      41
        •  Проверенный
      9 авг в 08:32

      Артём, добрый день!

      Вот весь код:

      <html lang="ru">
          <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
      </head>
      <body>
      <?php
      ini_set('error_reporting', E_ALL);
      ini_set('display_errors', 1);
      ini_set('display_startup_errors', 1);
      function get_currency_tr($currency_code = 'R01235') {
      
      	$date_start = date('d/m/Y', strtotime('-30 days')); // Дата начала выборки
      	$date = date('d/m/Y'); // Текущая дата (используется для кэша и для конца выборки)
      
      	$cache_time_out = 86400; // Время жизни кэша в секундах
      
      	$file_currency_cache = './currency.xml'; // Файл кэша
      
      	if(!is_file($file_currency_cache) || filemtime($file_currency_cache) < (time() - $cache_time_out)) {
      
      		$ch = curl_init();
      
      		curl_setopt($ch, CURLOPT_URL, 'https://www.cbr.ru/scripts/XML_dynamic.asp?date_req1='.$date_start.'&date_req2='.$date.'&VAL_NM_RQ='.$currency_code);
      		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
      		curl_setopt($ch, CURLOPT_HEADER, 0);
      
      		$out = curl_exec($ch);
      
      		curl_close($ch);
      
      		file_put_contents($file_currency_cache, $out);
      
      	}
      
      	$content_currency = simplexml_load_file($file_currency_cache);
      
      $content_currency_result = [];
      
      foreach($content_currency->Record as $currency) {
      
      	$content_currency_result[0][] = ' '.$currency->attributes()->Date.' ';
      	$content_currency_result[1][] = str_replace(',', '.', $currency->Value);
      
      }
      
      	return $content_currency_result;
      
      }
      
      $currencyArr = get_currency_tr('R01235');
      $currency_tr = '';
      
      for($i = 0; $i < count($currencyArr[0]); $i++) {
      	
      
      $td_3 = '';
      
      if(!is_null($currencyArr[1][$i - 1])) {
      
      	$td_3 = number_format(str_replace(',', '.', ($currencyArr[1][$i] - $currencyArr[1][$i - 1])), 4);
      
      	if($td_3 > 0) {
      
      		$td_3 = '<span style="color: green;">+'.$td_3.'</span>';
      
      	} elseif($td_3 < 0) {
      
      		$td_3 = '<span style="color: red;">'.$td_3.'</span>';
      
      	} else {
      
      		$td_3 = '<span style="color: black;">'.$td_3.'</span>';
      
      	}
      
      }
      
      $currency_tr .= '
      
      	<tr>
      		<td>'.$currencyArr[0][$i].'</td>
      		<td>'.$currencyArr[1][$i].'</td>
      		<td>'.$td_3.'</td>
      	</tr>
      
      ';
      	
      }
      	
      ?>
      <div class="currency-exchange">
          <div class="ce-title">Таблица изменений курса доллара США за 30 дней</div>
          <table border="1" width="500" class="table table-condensed ce-table">
              <thead>
                  <tr>
                      <td>Дата</td>
                      <td>Курс рублей за 1 usd</td>
                      <td>Изменение</td>
                  </tr>
              </thead>
              <tbody>
                  <?php echo $currency_tr; ?>
              </tbody>
          </table>
      </div>
      </body>
      </html>
      • 0
      1066
        •  Команда Pandoge
      9 авг в 12:50

      Илья, здравствуйте!

      if(!is_null($currencyArr[1][$i - 1])) {

      замените на:

      if(isset($currencyArr[1][$i - 1])) {
      • 1
      41
        •  Проверенный
      9 авг в 13:53

      Артём, спасибо большое! Теперь все отлично. Вот результат: https://skr.sh/sFLSp7TJ1o0?a

    • 1
    2
      •  Пользователь
    26 фев в 08:58

    Подскажите куда это прописать то ? echo get_currency("USD", 3);

      • 4
      2
        •  Пользователь
      26 фев в 12:45

      Что то не работает вас скрипт все белое

      • 3
      1066
        •  Команда Pandoge
      изменено 29 фев в 03:39

      Михаил Зав, здравствуйте! Слишком мало информации.

      Что показывают логи сервера?

      На какой CMS используете код?

      Сохраняется ли файл с данными валют?

    • 0
    1
      •  Пользователь
    23 сен в 19:41

    А реально такое только в С++ и для Arduino?

      • 1
      1066
        •  Команда Pandoge
      23 сен в 22:29

      Андрей Ка, с C++ знаком очень мало, а с Arduino только в качестве общего представления, поэтому с Вашей задачей, к сожалению, я помочь не смогу.

    • 1
    766
      •  Гости
    23 авг в 15:13

    Добрый день

    Как сделать вывод только двух знаков после запятой? Сейчас 4

      • 4
      1066
        •  Команда Pandoge
      23 авг в 23:13

      Андрей, нужную валюту оберните в round. На примере доллара это будет выглядеть так:

      echo "Доллар - ".round($usd, 2);

    • 1
    766
      •  Гости
    22 июн в 11:32

    а данный скрипт буден работать на сайте ( Opencart 2.3, https) ?

      • 2
      1066
        •  Команда Pandoge
      22 июн в 13:06

      Николай, Да.

    • 1
    766
      •  Гости
    12 мая в 04:20

    Во-первых, в настройках системы можно указать критический порог изменения курса валюты в процентах или рублях. Если он превышен, незамедлительно отправляется sms и e-mail сообщения.

    • 3
    766
      •  Гости
    13 апр в 21:37

    Спасибо! Как подключить обработчик на DLE?

    • 4
    766
      •  Гости
    6 мар в 19:26

    Работает конечно, но через раз! После ctrl+f5 то показывает то пропадает как решить?

      • 9
      1066
        •  Команда Pandoge
      6 мар в 19:34

      Павел, Я даже не представляю как вы там реализовали вывод, но предположу, что кэширование данных исправить эту ситуацию.

      Грузите файл к себе на сервер и проверяйте: если файлу больше двух часов - значит нужно его обновить, если нет - то используете тот что на вашем сервере.

      А вообще, обновлять файл можно и раз в день. ЦБ не так часто обновляет данные.

    • 1
    766
      •  Гости
    26 фев в 15:47

    Здравствуйте, как вывести дату и разницу, наподобие вашего информера?

      • 10
      1066
        •  Команда Pandoge
      26 фев в 19:50

      Павел, делаете два запроса - 1 запрос на сегодняшнюю дату, а 2 - на вчерашнюю.

      Получаете данные за оба дня и вычитаете одно из другого.

      • 0
      41
        •  Проверенный
      30 июл в 23:20

      Артём, можете примером написать? Я тоже увидел в магазине расширений информер курса валют. Получилось здорово!

      Особенно, если курс улучшается, то зеленым цветом, если наоборот, то красным цветом.

    • 4
    766
      •  Гости
    16 фев в 10:57

    А курсы получаем только по отношению к рублю?

    есть ли возможность например EURJPY?

    • 1
    766
      •  Гости
    13 фев в 01:30

    Здравствуйте!

    можно сделат http://cbu.uz/uzc/arkhiv-kursov-valyut/xml/

    • 0
    766
      •  Гости
    4 фев в 14:21

    классная вещь, а можно сделать так же, только с казахстанского национального банка http://www.nationalbank.kz/rss/rates.xml ?

      • 7
      1066
        •  Команда Pandoge
      4 фев в 14:28

      Родион, можно. В ближайшее время сделаем.

      -----

      Готово - https://www.pandoge.com/moduli_i_skripty/poluchaem-kursy-valyut-s-sayta-nacionalnogo-banka-kazahstana-na-php

    • 1
    766
      •  Гости
    3 ноя в 22:43

    А если нужен только доллар? Перебор foreach не нужен?

      • 6
      1066
        •  Команда Pandoge
      4 ноя в 01:32

      Дмитрий, да, foreach не нужен. Пример на долларе будет такой:

      echo $content->xpath('Valute[@ID="R01235"]')[0]->Value;

Подняться наверх
«Pandoge» - помощник вебмастера