[PHP] kurs walut – podejście trzecie – cześć 1

  1. Najprostsza metoda na wyświetlenie aktualnego kursu jest banalna. Należny pobrać stronę NBP z kursem, wyrzucić śmieci, pozostawić kursy walut, a na koniec wyświetlić upragnioną tabelkę. Ci bardziej wyrafinowani i nowocześni programiści pomijają oczywiście parsowanie strony NBP na rzecz bardziej eleganckiego rozwiązania jakim jest analiza pliku XML udostępnionego również przez NBP (oczywiście właśnie do tego celu).
    Pytanie zatem po co bawić się w zawiłe wyłuskiwanie kolejnych walut z tabelki enbepu jak mamy gotowy plik XML – hmm…. pewnie po nic. Nie przychodzi mi do głowy żadne normalne wytłumaczenie… ale nie to tego zmierzam.
  2. Wyświetlenie aktualnego kursu nie jest niczym szczególnym, daje jedynie bieżącą informację – a to już coś. Jednak w tej zabawie istnieje coś jeszcze… – możliwość dalszej rozbudowy jakże trywialnej “aplikacji”. Osoby bardziej ambitne nie poprzestaną przecież tylko na tym. Pamiętajmy przecież, że jeżeli oglądalność serwisu wzrasta, czas ładowania strony wydłuża się diametralnie i to tylko dlatego, że chcemy pokazać aktualny kurs walut. Łączenie się przy każdym wyświetleniu strony z serwerem NBP, nie przyniesie nam niczego dobrego. Może troszkę matematyki. Jeżeli w ciągu godziny nasz serwis odwiedzi 10 osób, przeglądnie tam 5 podstron, to mamy łącznie 50 odwołań na godzinę do NBP + 50 * 0.5 sekundy na pobranie i wygenerowanie kursu walut (jakieś 25 sek.) – niby nic. Pewnie w NBP nikt się nie połapie. Co jednak w sytuacji, jeżeli nasz serwis odwiedzi 150 osób i przeglądnie 15 po podstron – wtedy już mamy 2,250 zapytań do NBP + prawie 19 min. straty na łączenie się, przetwarzanie i generowanie kursu walut.
  3. Po głowie chodzi mi jedno rozsądne rozwiązanie. Oczywiście chodzi tu o pobieranie kursu raz dziennie (ponieważ częściej się on nie zmienia) i zapisanie go, albo do pliku tekstowego, albo do bazy danych. Problem z głowy…. Przy każdym wyświetleniu naszej strony kurs jest w mgnieniu oka pobierany z naszego serwera, a odwołań do NBP mamy tylko 1 na dobę… i wystarczy…
  4. …a może chcielibyśmy pokazać na stronie coś czego nie ma na stronie NBP – coś co da użytkownikom dodatkową informację? Coś co podpowie im czy kurs waluty spada, czy rośnie… Wystarczy wtedy za zapisywać do pliku (lub bazy) notowania z każdego dnia i porównać dwa ostatnie ;)
  5. Jeżeli sukcesywnie zbieramy informacje, to nasza baza rozbudowuje się, a to daje nam kolejne możliwości rozbudowy niby trywialnego skryptu
    • porównanie kursów z dwóch dowolnych dat
    • wyświetlenie całej historii zmian kursu
    • generowanie wykresów
    • zwiększanie contentu na stronie, zwiększa nasze zaplecze dla SEO

To może mały kurs?
To co nam potrzebne

  • serwer z obsługą PHP
  • baza danych MySQL

Krok 1. – Struktura bazy danych

Tworzymy dwie tabele – jedna na nazwy walut, druga na pobierane kursy.

CREATE TABLE `waluta` (
    `id` int(11) NOT NULL auto_increment,
    `nazwa` varchar(255) NOT NULL default '',
    `opis` varchar(255) NOT NULL default '',
    UNIQUE KEY `id` (`id`),
    UNIQUE KEY `nazwa` (`nazwa`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
  • id – indeks kursu walut, po którym będziemy odwoływac się w tabeli ‘kurs’
  • nazwa – nazwa waluty (np. USD)
  • opis – opis, czyli np. kod waluty (łącznie z jednostką) – np. 100 JPY
CREATE TABLE `kurs` (
    `id` int(11) NOT NULL auto_increment,
    `waluta` int(11) NOT NULL default '0',
    `kupno` decimal(8,4) NOT NULL default '0.0000',
    `sprzedaz` decimal(8,4) NOT NULL default '0.0000',
    `data` date default '0000-00-00',
    UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
  • id – indeks wpisu
  • waluta – id waluty z tabeli ‘waluta’
  • kupno – cena kupna
  • sprzedaz – cena sprzedaży
  • data – data wpisu

Krok 2. – Pobieranie kursu walut

Tworzymy klasę: nbp.class.php

class Nbp
{
    // plik z kursami walut w wersji HTML
    private $nbpHtmlFile = "http://nbp.pl/kursy/kursyc.html";

    // pobieramy aktualny kurs walut
    public function getFromNbp()
    {
        $this->nbpContent = strip_tags ($this->getFile( $this->nbpHtmlFile ));
        preg_match_all("/(.*)*/", $this->nbpContent, $matches_t);

        $offset = 6;
        for($i = 11; $i <= 27; $i++)
        {
            $a = $i . $offset;
            $date = date('Y-m-d');
            $name = preg_replace('/[^A-Z]/', '', $matches_t[0][$a] );

            $this->kurs[$date][$name]['desc'] = $matches_t[0][$a];
            $this->kurs[$date][$name]['purchase'] = str_replace(',', '.', $matches_t[0][$a+2]);
            $this->kurs[$date][$name]['sale'] = str_replace(',', '.', $matches_t[0][$a+4]);

            $offset+=2;
            if($offset == 10)
            {
                $i++;
                $offset = 0;
            }
        }
        return $this->kurs;
    }

    // metoda, która pobiera nam plik z kursem walut
    private function getFile($file_name)
    {
        $file = fopen($file_name, "r");
        while (!feof ($file))
        {
            $buffer = fgets($file, 4096);
            $out .= $buffer;
            if ( $buffer == "" )
            {
                fclose($file);
                return $out;
            }
        }
        fclose ($file);
        return $out;
    }
}

Krok 3. – Pierwszy test

Uruchamiamy naszą aplikację. Tworzymy plik import.php, a w nim wpisujemy

<?php
include_once './classes/nbp.class.php';

$kurs = New Nbp();
$kursOnline = $kurs->getFromNbp();

echo '<pre>' . print_r($kursOnline, true) . '</pre>';

…i jakby to powiedział Borat – …nice.
Czyli uzyskujemy coś takiego:

Array
(
   [2008-06-22] => Array
   (
        [USD] => Array
        (
                [desc] => 1 USD
                [purchase] => 2.1552
                [sale] => 2.1988
        )

        [AUD] => Array
        (
                [desc] => 1 AUD
                [purchase] => 2.0437
                [sale] => 2.0849
        )

        [CAD] => Array
        (
                [desc] => 1 CAD
                [purchase] => 2.1285
                [sale] => 2.1715
        )

        [EUR] => Array
        (
                [desc] => 1 EUR
                [purchase] => 3.3389
                [sale] => 3.4063
        )

        [HUF] => Array
        (
                [desc] => 100 HUF
                [purchase] => 1.3863
                [sale] => 1.4143
        )

        [CHF] => Array
        (
                [desc] => 1 CHF
                [purchase] => 2.0631
                [sale] => 2.1047
        )

        [GBP] => Array
        (
                [desc] => 1 GBP
                [purchase] => 4.2447
                [sale] => 4.3305
        )

        [JPY] => Array
        (
                [desc] => 100 JPY
                [purchase] => 1.9982
                [sale] => 2.0386
        )

        [CZK] => Array
        (
                [desc] => 1 CZK
                [purchase] => 0.1386
                [sale] => 0.1414
        )

        [DKK] => Array
        (
                [desc] => 1 DKK
                [purchase] => 0.4476
                [sale] => 0.4566
        )

        [EEK] => Array
        (
                [desc] => 1 EEK
                [purchase] => 0.2133
                [sale] => 0.2177
        )

        [NOK] => Array
        (
                [desc] => 1 NOK
                [purchase] => 0.4150
                [sale] => 0.4234
        )

        [SEK] => Array
        (
                [desc] => 1 SEK
                [purchase] => 0.3552
                [sale] => 0.3624
        )

        [XDR] => Array
        (
                [desc] => 1 XDR
                [purchase] => 3.4761
                [sale] => 3.5463
        )
   )
)

Dalsza cześć kursu już niedługo, a w nim:

  • Połączenie z bazą danych
  • Zbieranie informacji, czyli zapychanie bazy danymi
  • Zbieranie informacji, czyli uruchamiamy crona
  • Wyświetlany aktualny kurs
  • Wyświetlany kurs łącznie z analizą kursu wczorajszego
  • Przeglądamy historię zmian kursów
  • Porównujemy kursy z dwóch różnych dat
  • Generujemy wykresy
Share:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Gwar
  • Netvibes
  • Blip