1
\$\begingroup\$

I need:

  1. Daily save new exchange rates from the REST API in the database.

  2. Return the current exchange rate for a given currency, the whole table for a given day, the exchange rate for a given currency depending on the given currency and convert currency.

The code works, but I know it should not look that way. I do not know how to write it better.

2019_01_31_155244_create_nbp_rates_table.php

<?php
 use Illuminate\Support\Facades\Schema;
 use Illuminate\Database\Schema\Blueprint;
 use Illuminate\Database\Migrations\Migration;
 class CreateNbpRatesTable extends Migration
 {
 /**
 * Run the migrations.
 *
 * @return void
 */
 public function up()
 {
 Schema::connection('mysql_nbp')->create('rates', function (Blueprint $table) {
 $table->increments('id');
 $table->char('no', 20)->unique();
 $table->date('effectiveDate')->unique();
 $table->json('table_a');
 $table->timestamps();
 });
 }
 /**
 * Reverse the migrations.
 *
 * @return void
 */
 public function down()
 {
 Schema::connection('mysql_nbp')->dropIfExists('rates');
 }
 }

NBP.php - model

<?php
 namespace Modules\NBP\Entities;
 use Illuminate\Database\Eloquent\Model;
 use Exception;
 use GuzzleHttp\Client;
 use GuzzleHttp\Exception\RequestException;
 class NBP extends Model
 {
 protected $table = 'rates';
 protected $connection = 'mysql_nbp';
 protected $fillable = [
 'no', 'effectiveDate', 'table_a'
 ];
 public $date;
 protected $_ratesCurrent;
 protected $_ratesByDate;
 function __construct()
 {
 parent::__construct();
 }
 public function getCurrentRates()
 {
 return $this->getByDateRates(self::max('effectiveDate'));
 }
 public function getByDateRates($date)
 {
 $this->date = $date;
 $this->validatedDate();
 while (true) {
 $result = self::where('effectiveDate', $this->date)->get()->toArray();
 if (count($result) == 0) {
 $this->date = date('Y-m-d', strtotime($this->date . "-1 days"));
 } else {
 $result = self::where('effectiveDate', $this->date)->get()->toArray();
 $this->effectiveDate = $result[0]['effectiveDate'];
 $this->no = $result[0]['no'];
 $this->table = json_decode($result[0]['table_a'], true);
 $this->_ratesByDate = $this->generateTable();
 break;
 }
 }
 return $this->_ratesByDate;
 }
 public function getCurrentRateByIso($iso)
 {
 if (!isset($this->_ratesCurrent)) {
 $this->getCurrentRates();
 }
 if (array_key_exists($iso, $this->_ratesCurrent)) {
 return $this->_ratesCurrent[$iso];
 } else {
 throw new Exception('Brak kursu dla podanego kodu ISO', 400);
 }
 }
 public function getByDateRateByIso($iso, $date)
 {
 $this->date = $date;
 $this->validatedDate();
 $this->getByDateRates($date);
 if (array_key_exists($iso, $this->_ratesByDate)) {
 return $this->_ratesByDate[$iso];
 } else {
 throw new Exception('Brak kursu dla podanego kodu ISO', 400);
 }
 }
 public function exchange($isoFrom, $isoTo, $amount, $date = false)
 {
 if (!is_numeric($amount)) {
 throw new Exception('Nieprawidłowa kwota', 400);
 }
 $this->date = $date;
 if ($isoFrom == $isoTo) {
 return $amount;
 }
 if ($this->date === false) {
 $this->date = date('Y-m-d');
 } else {
 $this->validatedDate();
 }
 if ($isoFrom == 'PLN') {
 return $amount * $this->getByDateRateByIso($isoTo, $this->date);
 }
 if ($isoTo == 'PLN') {
 return $amount / $this->getByDateRateByIso($isoFrom, $this->date);
 }
 return $amount * $this->getByDateRateByIso($isoFrom, $this->date) / $this->getByDateRateByIso($isoTo, $this->date);
 }
 private function validatedDate()
 {
 if (!$this->date) {
 throw new Exception('Brak daty', 400);
 }
 try {
 new \DateTime($this->date);
 $this->date = date('Y-m-d', strtotime($this->date));
 } catch (\Exception $e) {
 throw new Exception('Nieprawidłowy format daty', 400);
 }
 }
 private function generateTable()
 {
 if (!$this->table) {
 throw new Exception('Brak wyników', 400);
 }
 $rates = [];
 foreach ($this->table as $rate) {
 $rates[(string) $rate['code']] = $rate['mid'];
 }
 $this->rates = $rates;
 return $this->rates;
 }
 public function downloadNowTables() {
 $begin = new \DateTime(date('Y-m-d', strtotime('- 1 week')));
 $end = new \DateTime(date('Y-m-d'));
 $end = $end->modify('+1 day');
 $interval = new \DateInterval('P1D');
 $daterange = new \DatePeriod($begin, $interval, $end);
 $GuzzleClient = new Client([
 'base_uri' => 'http://api.nbp.pl/api/',
 'defaults' => [
 'headers' => ['Accept' => 'application/json']
 ]
 ]);
 foreach ($daterange as $date) {
 var_dump($date->format("Y-m-d"));
 while (true) {
 try {
 if (self::where('effectiveDate',$date->format("Y-m-d"))->count() == 0) {
 $response = $GuzzleClient->get('exchangerates/tables/a/' . $date->format("Y-m-d"));
 $array = json_decode($response->getBody(), true);
 $rates = [];
 foreach ($array[0]['rates'] as $rate) {
 $rates[$rate['code']] = $rate;
 }
 self::insert([
 'no' => $array[0]['no'],
 'effectiveDate' => $array[0]['effectiveDate'],
 'table_a' => json_encode($rates),
 'created_at' => date('Y-m-d H:i:s'),
 'updated_at' => date('Y-m-d H:i:s')
 ]);
 }
 break;
 } catch (RequestException $e) {
 if (strpos($e->getMessage(), 'Brak danych')) {
 break;
 }
 }
 }
 }
 }
 }
Ludisposed
11.8k2 gold badges41 silver badges91 bronze badges
asked Feb 4, 2019 at 12:16
\$\endgroup\$
2
  • \$\begingroup\$ I need? Does the code below completes to two tasks? \$\endgroup\$ Commented Feb 4, 2019 at 14:10
  • \$\begingroup\$ Yes. It is working fine now and I need your opinions on the things I have done in this code to improve myself. \$\endgroup\$ Commented Feb 5, 2019 at 11:48

1 Answer 1

1
\$\begingroup\$

The API's URL is harcoded here, shouldn't it be better to use a configuration file? What if you want to use a different one or the API owners change the address?

'base_uri' => 'http://api.nbp.pl/api/',
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
answered Feb 5, 2019 at 21:30
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.