0

Using the code below, I get an XML with the exchange rate on a given date. However, sometimes there are no quotes for a given date and an error is returned to me. In such cases, I would like to do minus one day by a given date and get the data again. If there is another error, again minus one day. As soon as the correct XML is obtained, we cache it (now I cache everything received for 6 hours).

function get_currency($currency_code, $setDate, $format)
{
    $date = $setDate;
    $cache_time_out = '21600';
    $filename = date('d-m-Y', strtotime($date)) . '.xml';

    $file_currency_cache = __DIR__ . '/cache/' . $filename;

    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-xml-daily.ru/archive/' . $date . '/daily_utf8.xml');
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0);
        curl_setopt($ch, CURLOPT_TIMEOUT, 50);

        $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);
}

I show the result of parsing on the site like this:

$date = '2014/06/02';
$ex_rate_usd = get_currency('USD', $date, 3);
echo $ex_rate_usd;

I found this code on the web and it works correctly, but problems with the lack of currency quotes for some dates break everything. I will be grateful for any help in this matter.

3
  • 1
    $date = 2014/06/02; would give 167.83333333333 and not a date. Commented May 17, 2022 at 8:30
  • 1
    Sorry, I corrected it, I have a variable with a date there). $date = '2014/06/02'; Commented May 17, 2022 at 8:31
  • Hey, bro, what is your expectation? Commented May 17, 2022 at 9:17

1 Answer 1

1

SimpleXMLElement->xpath() always returns an array (for a valid Xpath expression). But this array can be empty. You access a property of the first element of the result array without validating that it exists.

$valute = $content_currency->xpath('Valute[CharCode="'.$currency_code.'"]')[0]
$rate = $valute ? $valute->value : null;

If you select an attribute with the xpath expression then you can simplify this a little:

$rate = (string)(
  $content_currency->xpath('Valute[CharCode="'.$currency_code.'"]/@value')[0] ?? ''
)

With DOM Xpath can return scalar values:

$document = new DOMDocument();
$document->loadXML($file_currency_cache);
$xpath = new DOMXpath($document);

$rate = $xpath->evaluate(
  'number(//Valute[CharCode="'.$currency_code.'"]/@value)'
);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.