I need:
Daily save new exchange rates from the REST API in the database.
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;
}
}
}
}
}
}