Повторное использование функции PHP для доступа к тегу элемента массива из документа XML - PullRequest
0 голосов
/ 02 февраля 2012

Я создал веб-сайт, который использует XML для управления некоторым его содержимым, например, текущими курсами обмена, как показано ниже.

enter image description here Веб-сайт сравнивает три обменных курса, и в настоящее время я использую отдельные функции для каждого города, которые выполняют идентичные цели, например возврат текущих обменных курсов.

Единственное отличие между этими функциями - это позиции тега элемента в документе XML, из которого я запрашиваю данные.

  $exchange['rate'] = $xml->channel->item[15]->description;

Уведомление элемент [15] в вышеуказанном массиве, который обеспечивает доступ к валюте евро. Далее, валютой США является пункт [56] , как показано ниже.

  $exchange['rate'] = $xml->channel->item[56]->description;

Есть какие-нибудь идеи, если возможно объединить три функции в одну для повышения сплоченности?

Функция доступа к валюте евро, которую я использую:

<?php

function get_rate1(SimpleXMLElement $xml) {

    // Match numeric values before and after decimal place
    $exchange['rate'] = $xml->channel->item[15]->description;
    preg_match('/([0-9]+\.[0-9]+)/', $exchange['rate'], $matches);
    $rate = $matches[0];

    // Get currency type from title
    $title['rate'] = $xml->channel->item[15]->title;
    $title = explode('/', $title['rate']);
    $title = $title[0];

    echo $rate . ' ' . $title . '<br />';

    return $rate;
}

?>

URL-адреса фидов задаются в другом конфигурационном скрипте с именем cityConfig.php

<?php

// City 1 //
$city1 = 'Paris';
$exchangeRate1 = '1 Euro';
$exchangeRate1RssUrl = 'http://themoneyconverter.com/rss-feed/EUR/rss.xml';

?>

Заранее спасибо

Ответы [ 3 ]

2 голосов
/ 02 февраля 2012

Попробуйте по размеру - он использует трехбуквенные коды валют и использует XPath для их поиска, полностью избавившись от этих неприятных индексов. Все, что вам нужно предоставить, - это трехбуквенный код исходной валюты и трехбуквенный код получателя или массив получателей, если вы хотите получить более одного сразу.

MODIFIED , поэтому $dest теперь необязательно. Если указано только $source, вернуть массив всех обменных курсов.

function get_rate ($source, $dest = NULL) {

  // Make sure source currency is upper case
  $source = strtoupper($source);

  // Construct the source URL
  $url = "http://themoneyconverter.com/rss-feed/$source/rss.xml";

  // This will hold the results
  $result = array();

  // Fetch and parse the data
  if (!$xml = simplexml_load_file($url)) {
    return FALSE;
  }

  if ($dest === NULL) {

    // Get all <item> nodes and loop them
    foreach ($xml->xpath("//item") as $item) {

      // Find the code of this currency
      $currencyParts = explode('/', $item->title);

      // Get the value of this currency
      $result[$currencyParts[0]] = (preg_match('/([0-9]+\.[0-9]+)/', $item->description, $matches)) ? (float) $matches[0] : FALSE;

    }

  } else {

    // Loop the destination currencies
    foreach ((array) $dest as $currency) {

      // Make sure destination currencies are upper case
      $currency = strtoupper($currency);

      // Perform an XPath search for this currency
      $nodes = $xml->xpath("//item[title='$currency/$source']/description");

      // If we found the currency and could extract the value, add it to the
      // result array as a float
      $result[$currency] = (count($nodes) === 1 && preg_match('/([0-9]+\.[0-9]+)/', $nodes[0], $matches)) ? (float) $matches[0] : FALSE;

    }

  }

  // If only a single value was requested return it, otherwise return the array
  return (count($result) === 1) ? array_shift($result) : $result;

}

Пример использования:

$result = get_rate('GBP', 'USD');
var_dump($result);
/*
  float(1.58014)
*/

$result = get_rate('GBP', array('USD', 'EUR'));
var_dump($result);
/*
  array(2) {
    ["USD"]=>
    float(1.58014)
    ["EUR"]=>
    float(1.20236)
  }
*/

$result = get_rate('GBP');
var_dump($result);
/*
  array(64) {
    ["AED"]=>
    float(5.80445)
    ["ARS"]=>
    float(6.85316)
    ["AUD"]=>
    float(1.47589)
    ["BBD"]=>
    float(3.16103)
    ["BHD"]=>
    float(0.59427)
    ["BOB"]=>
    float(10.92135)
    ["BRL"]=>
    float(2.72171)
    ["CAD"]=>
    float(1.57968)
    ["CHF"]=>
    float(1.44883)
    ["CLP"]=>
    float(759.35947)
    ["CNY"]=>
    float(9.96753)
    ["COP"]=>
    float(2840.97943)
    ["CZK"]=>
    float(30.15863)
    ["DKK"]=>
    float(8.97219)
    ["EGP"]=>
    float(9.53446)
    ["EUR"]=>
    float(1.20265)
    ["HKD"]=>
    float(12.24901)
    ["HUF"]=>
    float(350.91425)
    ["IDR"]=>
    float(14121.92063)
    ["ILS"]=>
    float(5.87877)
    ["INR"]=>
    float(77.48491)
    ["ISK"]=>
    float(194.46687)
    ["JMD"]=>
    float(136.31954)
    ["JOD"]=>
    float(1.12059)
    ["JPY"]=>
    float(120.36272)
    ["KES"]=>
    float(132.28924)
    ["KRW"]=>
    float(1763.3828)
    ["KWD"]=>
    float(0.43897)
    ["LBP"]=>
    float(2382.62959)
    ["LKR"]=>
    float(180.02093)
    ["LTL"]=>
    float(4.1525)
    ["LVL"]=>
    float(0.84522)
    ["MAD"]=>
    float(13.39206)
    ["MXN"]=>
    float(20.24582)
    ["MYR"]=>
    float(4.77078)
    ["NAD"]=>
    float(12.10631)
    ["NGN"]=>
    float(253.27781)
    ["NOK"]=>
    float(9.21948)
    ["NPR"]=>
    float(123.97585)
    ["NZD"]=>
    float(1.89597)
    ["OMR"]=>
    float(0.6077)
    ["PAB"]=>
    float(1.58052)
    ["PEN"]=>
    float(4.25316)
    ["PHP"]=>
    float(67.48803)
    ["PKR"]=>
    float(142.95779)
    ["PLN"]=>
    float(5.03909)
    ["QAR"]=>
    float(5.75308)
    ["RON"]=>
    float(5.23271)
    ["RUB"]=>
    float(47.73085)
    ["SAR"]=>
    float(5.92694)
    ["SEK"]=>
    float(10.66422)
    ["SGD"]=>
    float(1.96993)
    ["THB"]=>
    float(48.79218)
    ["TRY"]=>
    float(2.77931)
    ["TWD"]=>
    float(46.6742)
    ["UAH"]=>
    float(12.71293)
    ["USD"]=>
    float(1.58052)
    ["UYU"]=>
    float(30.74107)
    ["VEF"]=>
    float(6.79622)
    ["VND"]=>
    float(33119.73602)
    ["XAF"]=>
    float(788.88394)
    ["XCD"]=>
    float(4.2674)
    ["XOF"]=>
    float(788.88394)
    ["ZAR"]=>
    float(12.10631)
  }
*/
1 голос
/ 02 февраля 2012

Поскольку я пока не могу комментировать ... ответ Хелка идеален - вы можете сделать еще один шаг вперед и определить некоторые константы класса или определить константы (), чтобы вам не приходилось иметь дело с трудно запоминающимися числами в вашемкод (помните, что вы, возможно, не единственный человек, который когда-либо смотрит на этот код - вы знаете, что такое 15, но младший Дэв Ньюгуай этого не делает):

<?php

define('CURRENCY_USA', 56);
define('CURRENCY_EURO', 15);

// OR something like:
class CurrencyHelper
{
    const CURRENCY_USA = 56;
    const CURRENCY_EURO = 15;

    // of course, you could also define get_rate here too...
    public function __construct(SimpleXmlElement $xml)
    {
        $this->xml = $xml;
    }  

    public function get_rate($id)
    {
      // ... your code here
    }
}

// Or, define your get_rate as originally intended:

function get_rate(SimpleXMLElement $xml, $id) {

    // Match numeric values before and after decimal place
    $exchange['rate'] = $xml->channel->item[$id]->description;
    preg_match('/([0-9]+\.[0-9]+)/', $exchange['rate'], $matches);
    $rate = $matches[0];

    // Get currency type from title
    $title['rate'] = $xml->channel->item[$id]->title;
    $title = explode('/', $title['rate']);
    $title = $title[0];

    echo $rate . ' ' . $title . '<br />';

    return $rate;
}

// Finally:
echo get_rate($xml, CURRENCY_EURO); // define
echo get_rate($xml, CurrencyHelper::CURRENCY_USA; // class constant
$myCurr = new CurrencyHelper($xml);
$myCurr->get_rate(CurrencyHelper::CURRENCY_USA); // Over-oop'd solution : P

?>
1 голос
/ 02 февраля 2012

Как насчет того, чтобы изменить функцию тарифа следующим образом:

<?php

function get_rate(SimpleXMLElement $xml, $id) {

    // Match numeric values before and after decimal place
    $exchange['rate'] = $xml->channel->item[$id]->description;
    preg_match('/([0-9]+\.[0-9]+)/', $exchange['rate'], $matches);
    $rate = $matches[0];

    // Get currency type from title
    $title['rate'] = $xml->channel->item[$id]->title;
    $title = explode('/', $title['rate']);
    $title = $title[0];

    echo $rate . ' ' . $title . '<br />';

    return $rate;
}

?>

Тогда вы можете вместо этого вызвать ее так:

$rate1 = get_rate($xml,15);
$rate2 = get_rate($xml,56);
...