Git Product home page Git Product logo

laravel-currency's Introduction

Currency component for Laravel 9

Installation

Install the package using composer

composer require sebastiansulinski/laravel-currency

Service Provider and Facade

To use the package with the IOC Container, add its SSD\Currency\CurrencyServiceProvider to the list of providers inside of the config/app.php under the providers:

'providers' => [
    ...

    SSD\Currency\CurrencyServiceProvider::class

]

To use it as a Facade, add it under the aliases:

'aliases' => [
    ...

    'Currency'  => SSD\Currency\CurrencyFacade::class
]

now run:

php artisan vendor:publish

This will add a new file config/currency.php with the following structure:

<?php

return [
    "key" => "currency",
    "default" => \SSD\Currency\Currencies\GBP::code(),
    "currencies" => [
        \SSD\Currency\Currencies\GBP::class,
        \SSD\Currency\Currencies\USD::class,
        \SSD\Currency\Currencies\EUR::class,
    ],
    "value_as_integer" => false,
];
  • The key is used as the session key, which stores the currently selected currency.
  • The default states the default currency code.
  • The currencies contains a list of available currencies.
  • The value_as_integer indicates whether your prices are stored as integers or float / decimal.

Provider

Package comes with two implementations / providers:

  • SSD\Currency\Providers\CookieProvider, which stores selected currency in the encrypted cookie
  • SSD\Currency\Providers\SessionProvider, which will store the selected currency using default session driver

You can create additional providers by:

  • extending SSD\Currency\Providers\BaseProvider

There are 3 methods that the new Provider needs to implement - these are: get, set and is. Please see SSD\Currency\Providers\CookieProvider to get a better idea.

Once you have a new implementation ready, create the new ServiceProvider and replace it within config/app.php.

Adding more currencies

Package comes with 3 currencies out of the box: GBP, USD, EUR.

If you'd like to add more, first create a new currency class, which:

  • extends SSD\Currency\Currencies\BaseCurrency

For instance, implementation for Japanese Yen would be (assuming you keep your currencies under App\Components\Currencies namespace):

<?php 

namespace App\Components\Currencies;

use SSD\Currency\Currencies\BaseCurrency;

class JPY extends BaseCurrency
{
    /**
     * Get symbol.
     *
     * @return string
     */
    public static function symbol(): string
    {
        return '¥';
    }

    /**
     * Get code.
     *
     * @return string
     */
    public static function code(): string
    {
        return 'JPY';
    }
}

All you need to do now to be able to use it is to add it to the config/currency.php file:

<?php

return [
    "key" => "currency",
    "default" => \SSD\Currency\Currencies\GBP::code(),
    "currencies" => [
        \SSD\Currency\Currencies\GBP::class,
        \SSD\Currency\Currencies\USD::class,
        \SSD\Currency\Currencies\EUR::class,
        \App\Components\Currencies\JPY::class,
    ],
    "value_as_integer" => false,
];

Currencies with symbol after the value

Some currencies place symbol after the value. To indicate it you can overwrite the method BaseCurrency::symbolAfterValue and if you need a space between the symbol and value BaseCurrency::symbolSpace:

<?php 

namespace App\Components\Currencies;

use SSD\Currency\Currencies\BaseCurrency;

class PLN extends BaseCurrency
{
    /**
     * Get symbol.
     *
     * @return string
     */
    public static function symbol(): string
    {
        return '';
    }

    /**
     * Get code.
     *
     * @return string
     */
    public static function code(): string
    {
        return 'PLN';
    }

    /**
     * Determine if symbol should be placed after the value.
     *
     * @return bool
     */
    protected static function symbolAfterValue(): bool
    {
        return true;
    }

    /**
     * Determine if there is a space between symbol and the value.
     *
     * @return bool
     */
    protected static function symbolSpace(): bool
    {
        return true;
    }
}

The above class would now return 75.00 zł with withSymbol and 75.00 zł PLN with withSymbolAndCode methods.

Usage examples

The most common way of displaying currencies is to either have them displayed as clickable buttons or as a form select menu, which is what I'm going to demonstrate below.

First let's create a form select element with all options displayed. We can either use a Currency facade or simply pull currency from within the container using app('currency'):

<form>
    <select id="currency">
        @foreach(app('currency')->options() as $option)
            <option 
                value="/currency/{{ $option->value }}"
                {{ app('currency')->selected($option->value) }}
            >{{ $option->label }}</option>
        @endforeach
    </select>
</form>

Now we need have some JavaScript so that when the change event occurs, the call is made to the given route, where action of the controller sets the new currency and page reloads reflecting that change.

Simply bind change event to the select element using JavaScript:

// vanilla JavaScript
(document.getElementById('currency')).addEventListener('change', function (event) {
    window.location.href = event.target.value;
});

// or using jQuery
$('#currency').on('change', function () {
    window.location.href = $(this).val();
});

Next we need to add the Controller with Action and Route for it:

// app/Http/routes.php

Route::get('currency/{currency_id}', 'CurrencyController@set');
// app/Http/Controllers/CurrencyController.php

<?php 

namespace App\Http\Controllers;

use Illuminate\Http\JsonResponse;

use Currency;

class CurrencyController extends Controller
{
    /**
     * Set currency cookie.
     *
     * @param $id
     * @return \Illuminate\Http\JsonResponse
     */
    public function set($id)
    {
        Currency::set($id);

        return new JsonResponse(['success' => true]);
    }
}

Now if you'd like to display price based on the selected currency, make sure that your model can provider an array of prices for a given item in the following format:

[
    'GBP' => 10.00,
    'EUR' => 11.56,
    'USD' => 17.60,
    'JPY' => 18.50
]

// or if you're using prices as integers

[
    'GBP' => 1000,
    'EUR' => 1156,
    'USD' => 1760,
    'JPY' => 1850
]

Let's assume our Product model has a prices() method, which will return the array formatted as above. To use it with the currency you can now simply call:

/**
 * Array of prices.
 *
 * @return array
 */
public function prices()
{
    return [
        'GBP' => $this->price_gbp,
        'EUR' => $this->price_usd,
        'USD' => $this->price_eur,
        'JPY' => $this->price_jpy
    ];
}

/**
 * Price formatted with the currency symbol.
 *
 * @return string
 */
public function priceDisplay()
{
    return Currency::withSymbol($this->prices(), null, 2);
}

The priceDisplay() method will return the price with the currency symbol i.e. £10.00 (depending on the currently selected currency).

Formatting methods

We have the following methods available on our Currency object instance / facade:

  • decimal($values, $currency = null, $decimal_points = 2) : gets the value and gives it back in the decimal format.
  • integer($values, $currency = null) : gets the value as integer i.e. 20.53 will become 20, but 2053 will be 2053.
  • withSymbol($values, $currency = null, $decimal_points = null) : gets the value and gives it back with the currency symbol at the beginning.
  • withCode($values, $currency = null, $decimal_points = null) : gets the value and gives it back with the currency code at the end.
  • withSymbolAndCode($values, $currency = null, $decimal_points = null) : gets the value and gives it back with the currency symbol and code.

Four of the above methods accept 3 arguments (integer method only first 2):

  • $values : either array as above or a single float / int
  • $currency : currency code - null by default, which is when the currency will be taken from the cookie - otherwise, you can state what currency you'd like to use.
  • $decimal_points : how many decimal points you'd like it to return the value with.

More methods

  • options() : returns an array of SSD\Currency\Option - each representing one currency. SSD\Currency\Option has 2 properties value and label.
  • selected($currency) : to be used with select option element to make the given option selected="selected" if it is set as current.
  • get() : gets currently selected currency.
  • set($currency) : sets the currency.
  • is($currency) : checks if the currency passed as argument is currently selected.

laravel-currency's People

Contributors

dependabot[bot] avatar nikspyratos avatar sebastiansulinski avatar ssdtutorials avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

laravel-currency's Issues

The currency array key is being saved

With no currencies selected, app('currency')->get() returns the currency code for the default currency.

Following your example, the index of the array is saved, not the currency code': @foreach(app('currency')->options() as $option) <option value="/currency/{{ $option->value }}" {{ app('currency')->selected($option->value) }} >{{ $option->label }}</option> @Endforeach The Option's value is the keyed integer from the array of currencies not the code: SSD\Currency\Option Object ( [value:SSD\Currency\Option:private] => 0 [label:SSD\Currency\Option:private] => GBP (£) ) So in subsequent calls to app('currency')->get(), it's just giving the integer, not the code.

Return error

Works beautifully on the local machine.
But it cause the error on the host.
Type error: Return value of SSD\Currency\Providers\CookieProvider::set() must be an instance of SSD\Currency\Providers\void, none returned

How to avoid prefix

Hi,

I am getting my prices in javascript and calculate them, for that matter i need to avoid prefixes and just get price it selves, how do i do that?

basic

$10

what i want

10

returning issue

Hi,

When I try to change my currency I get

Class 'App\Http\Controllers\Currency' not found

on

Currency::set($id);

here is my controller:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;

class CurrencyController extends Controller
{
    public function set($id)
    {
        Currency::set($id);
        return new JsonResponse(['success' => true]);
    }
}

so i added

use Currency;

and it's working now, BUT there is a big issue:

Except my page be reload with new currency i will redirect to json page like http://domain.pp/currency/eur and get success | true

Question

  1. What should I do to be redirected to the page and get my currency values instead of seeing json
    results?
  2. If I use 3 currency in my site, do I have to add 3 columns in my products table in order to set different price for each currency? or it gets the exchange rates from some api?

Target class [currency] does not exist.

Hi, hope you could assist with setup.

When installing, I noticed that php artisan vendor:publish did not display your package:

[0 ] Publish files from all providers and tags listed below
  [1 ] Provider: Asantibanez\LivewireCalendar\LivewireCalendarServiceProvider
  [2 ] Provider: Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider
  [3 ] Provider: BeyondCode\DumpServer\DumpServerServiceProvider
  [4 ] Provider: Cmgmyr\Messenger\MessengerServiceProvider
  [5 ] Provider: Facade\Ignition\IgnitionServiceProvider
  [6 ] Provider: Fideloper\Proxy\TrustedProxyServiceProvider
  [7 ] Provider: Fruitcake\Cors\CorsServiceProvider
  [8 ] Provider: Illuminate\Foundation\Providers\FoundationServiceProvider
  [9 ] Provider: Illuminate\Mail\MailServiceProvider
  [10] Provider: Illuminate\Notifications\NotificationServiceProvider
  [11] Provider: Illuminate\Pagination\PaginationServiceProvider
  [12] Provider: Intervention\Image\ImageServiceProviderLaravelRecent
  [13] Provider: Laravel\Tinker\TinkerServiceProvider
  [14] Provider: Livewire\LivewireServiceProvider
  [15] Provider: ProtoneMedia\LaravelFormComponents\Support\ServiceProvider
  [16] Provider: Spatie\MediaLibrary\MediaLibraryServiceProvider
  [17] Provider: Torann\GeoIP\GeoIPServiceProvider
  [18] Tag: config
  [19] Tag: cors
  [20] Tag: flare-config
  [21] Tag: ignition-config
  [22] Tag: laravel-errors
  [23] Tag: laravel-mail
  [24] Tag: laravel-notifications
  [25] Tag: laravel-pagination
  [26] Tag: livewire
  [27] Tag: livewire-calendar
  [28] Tag: livewire:assets
  [29] Tag: livewire:config
  [30] Tag: migrations
  [31] Tag: views

This was after adding the provider and alias to my config/app:

providers:

        SSD\Currency\CurrencyServiceProvider::class,
        ....

aliases:

        'Currency'     => SSD\Currency\CurrencyFacade::class,
        ....

I manually copied over the config to my /config.

But now the app('currency') is coming back with Target class [currency] does not exist..

Any hints? Appreciate your help

withPrefix $decimal_points default value

In the examples I see

withPrefix($values, $currency = null, $decimal_points = 2)

but if I run

Currency::withPrefix($item->price)

or

Currency::withPrefix($item->price, 'eur')

there are no decimals in the price returned.

Thank you

Can't get provider

I'm trying to set currency, but I get

Cannot access private property SSD\Currency\Currency::$provider

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.