Подготовка конфигурационного файла
В папке config создаем файл currency.php со следующим содержимым:
<?php
//валюты и курсы
return [
'code' => 'usd', //Внутренняя валюта
'precision' => 0, //Точность при конвертации сумм
'default' => 'rub', //Валюта пользователя по-умолчанию, если не удалось определить иную
'rates' => [
'usd' => [
'rub' => 75, //Покупка usd за рубли
],
'rub' => [
'usd' => 0.01333 //Покупка рублей за usd (продажа usd)
],
]
]
]
Готовим словарь с валютами
Для того, чтобы иметь гибкую возможность для разных языковых версий по-разному выдавать знак валюты или слово (например руб. или rub), создаем словарь, в котором определяем перевод для соответствующего кода валюты.
Создаем файл resources/lang/en/currency.php (можно создать также и для любого другого языка resources/lang/[код языка]/currency.php) со следующим содержимым:
<?php
return [
'rub' => '₽',
'usd' => '$'
];
Готовим главный класс сервиса Currency
В папке app/Services/Currency создаем класс CurrencyService.php со следующим содержимым:
<?php
namespace App\Services\Currency;
use App\Dictionary\BalanceTransactionOperationCode;
use App\Models\User;
/**
* Класс для работы с конвертацией внутренней валюты
* Class CurrencyService
* @package App\Services\Currency
*/
class CurrencyService
{
protected array $rates;
protected string $defaultCurrencyCode;
protected int $precision;
protected string $defaultUserCurrencyCode;
public function __construct(string $defaultCurrencyCode, array $rates, $defaultUserCurrencyCode, $precision = 2)
{
$this->rates = $rates;
$this->defaultCurrencyCode = $defaultCurrencyCode;
$this->precision = $precision;
$this->defaultUserCurrencyCode = $defaultUserCurrencyCode;
}
/**
* Получить валюту пользователя
* @return string
*/
public function getDefaultUserCurrency(){
//TODO здесь вы можете определить произвольную логику, по которой мы определяем валюту по-умолчанию для текущего пользователя (не важно, авторизованного или нет)
/** @var User $user */
$user = \Auth::user();
if($user) return $user->currency_code;
return $this->defaultUserCurrencyCode;
}
/**
* Конвертация из внутренней валюты во внешнюю
* @param $amount
* @param null $toCurrencyCode
* @return float
*/
public function convertFromDefault($amount, $toCurrencyCode = null){
if(!$toCurrencyCode){
$toCurrencyCode = $this->getDefaultUserCurrency();
}
$rate = $this->rates[$toCurrencyCode][$this->defaultCurrencyCode];
return round($amount / $rate, $this->precision);
}
/**
* Конвертация из внешней валюты во внутреннюю
* @param $amount
* @param null $fromCurrencyCode
* @return float
*/
public function convertToDefault($amount, $fromCurrencyCode = null){
if(!$fromCurrencyCode){
$fromCurrencyCode = $this->getDefaultUserCurrency();
}
$rate = $this->rates[$this->defaultCurrencyCode][$fromCurrencyCode];
return round($amount * $rate, $this->precision);
}
/**
* Конвертирует и возвращает отформатированную строку со знаком валюты
* @param $amount
* @return string
*/
public function convertAndFormatFromDefault($amount, $toCurrency = null){
if(!$toCurrency) {
$toCurrency = $this->getDefaultUserCurrency();
}
return number_format($this->convertFromDefault($amount, $toCurrency), 0, ',', ' ').__('currency.'.$toCurrency);
}
/**
* Конвертирует и возвращает отформатированную строку со знаком валюты
* @param $amount
* @return string
*/
public function convertAndFormatToDefault($amount, $fromCurrency = null){
if(!$fromCurrency) {
$fromCurrency = $this->getDefaultUserCurrency();
}
return number_format($this->convertFromDefault($amount, $fromCurrency), 0, ',', ' ').__('currency.'.$fromCurrency);
}
}
По комментариям и названию в doc-блоке функции можно понять, что делает та или иная функция.
Добавим сервис в контейнер
В файле app/Providers/AppServiceProvider.php в методе register() добавляем следующие строки инициализации нашего сервиса CurrencyService:
use App\Services\Currency\CurrencyService;
...
//В методе register()
$this->app->singleton(CurrencyService::class, function(){
return new CurrencyService(
config("currency.code"),
config("currency.rates"),
config("currency.default"),
config("currency.precision")
);
});
...
Уже можно пользоваться, но это еще не все
Теперь мы можем обращаться к нашему сервису. Например так:
<?php
...
$currencyService = \App::make(\App\Services\Currency\CurrencyService::class);
//Выведет на экране что-то вроде 86 250₽
echo $currencyService->convertAndFormatToDefault(1150, 'usd');
...
Создадим фасад и псевдоним для удобного обращения к сервису
Для более удобного обращения, создадим фасад и короткий alias.
Сначала создадим фасад. Создаем файл app/Facades/Currency.php со следующим содержимым:
<?php
namespace App\Facades;
use App\Services\Currency\CurrencyService;
use Illuminate\Support\Facades\Facade;
class Currency extends Facade
{
protected static function getFacadeAccessor()
{
return CurrencyService::class;
}
}
Этот фасад позволит нам обращаться к сервису в статической форме. Например так:
<?php
echo App\Facades\Currency::convertAndFormatToDefault(1150);
И теперь чтобы сделать обращение еще короче, добавим в файле config/app.php в настройке 'providers' следующую связь:
<?php
...
'providers' => [
...
'Currency' => App\Facades\Currency::class,
]
Теперь мы можем пользоваться в любом месте приложения такой записью:
<?php
...
echo Currency::convertAndFormatToDefault(1150);
В Blade-шаблонах:
...
{{ Currency::convertAndFormatToDefault(1150) }}
...
Создаем директиву Blade для отображения внутренней валюты в валюте пользователя
В файле app/Providers/AppServiceProvider.php в методе boot добавляем следующие строки кода:
<?php
use Illuminate\Support\Facades\Blade
...
public function boot()
{
...
//Директива позволяет выводить сумму во внутренней валюте, конвертированную в валюту пользователя
Blade::directive('currency_money', function ($amount) {
return "<?php echo Currency::convertAndFormatFromDefault($amount) ?>";
});
...
}
Теперь мы можем в Blade-шаблонах использовать еще более лаконичную запись:
@currency_money(1150)
или с динамическим значением:
@currency_money($sum)
Итог
Мы создали сервис Currency, который полностью настраивается через конфигурационный файл, в котором мы можем задавать курс валют и отображать их в различных местах вашего веб-приложения или сайта. Гибкость данного подхода в том, что в AppServiceProvider вы можете задать другой источник курсов валют — например какой-то внешний сервис или база данных. Также в методе getDefaultUserCurrency класса CurrencyService вы можете определить свою логику получения валюты пользователя по-умолчанию.
Удачи в веб-разработке! Если хочешь получать больше полезных материалов по Laravel, подписывайся на мой канал в Youtube: Lectoria. Обучение веб-разработке
Вы должны авторизоваться, чтобы оставлять комментарии.