2017 © Pedro Peláez
 

symfony-bundle money-bundle

This is a Symfony bundle that integrates moneyphp/money library (Fowler pattern): https://github.com/moneyphp/money.

image

ph-il/money-bundle

This is a Symfony bundle that integrates moneyphp/money library (Fowler pattern): https://github.com/moneyphp/money.

  • Wednesday, January 3, 2018
  • by phil
  • Repository
  • 1 Watchers
  • 1 Stars
  • 26 Installations
  • PHP
  • 0 Dependents
  • 0 Suggesters
  • 54 Forks
  • 0 Open issues
  • 31 Versions
  • 8 % Grown

The README.md

PhilMoneyBundle

Build Status PHP Symfony Downloads Latest Stable Version license, (*1)

This bundle is used to integrate the Money library from mathiasverraes into a Symfony project., (*2)

This bundle is a fork of TbbcMoneyBundle, (*3)

This library is based on Fowler's Money pattern, (*4)

  • This bundle is tested and is stable with Symfony 6.3+ and 7

Quick Start

use Money\Money;
use Phil\MoneyBundle\Form\Type\MoneyType;

// the money library
$fiveEur = Money::EUR(500);
$tenEur = $fiveEur->add($fiveEur);
list($part1, $part2, $part3) = $tenEur->allocate(array(1, 1, 1));
assert($part1->equals(Money::EUR(334)));
assert($part2->equals(Money::EUR(333)));
assert($part3->equals(Money::EUR(333)));

// a service that stores conversion ratios
$pairManager = $this->get('phil_money.pair_manager');
$usd = $pairManager->convert($tenEur, 'USD');

// a form integration
$formBuilder->add('price', MoneyType::class);

Features

  • Integrates money library from mathiasverraes
  • Twig filters and PHP helpers for helping with money and currencies in templates
  • A storage system for currency ratios
  • A ratioProvider system for fetching ratio from externals api
  • Symfony form integration
  • Console commands for different operations
  • A configuration parser for specifying website used currencies
  • Access to the history of currency ratio fetched
  • Money formatter i18n

Table of contents

Installation

Use Composer and install with
$ composer require phil/money-bundle, (*5)

For Symfony 6 and higher add the bundle to config/bundles.php (if it was not automatically added during the installation of the package):, (*6)

    return [
        // ...
        Phil\MoneyBundle\PhilMoneyBundle::class => ['all' => true],
    ];

For create a file like config/packages/phil_money.yml and add it there., (*7)

phil_money:
    currencies: ["USD", "EUR"]
    reference_currency: "EUR"
    decimals: 2

In your config.yml or config/packages/phil_money.yml, add the form fields presentations, (*8)

twig:
    form_themes:
        - '@PhilMoney/Form/fields.html.twig'

You should also register custom Doctrine Money type:, (*9)

doctrine:
    dbal:
        types:
            money: Phil\MoneyBundle\Type\MoneyType

Usage

Money Library integration

use Money\Money;

$fiveEur = Money::EUR(500);
$tenEur = $fiveEur->add($fiveEur);
list($part1, $part2, $part3) = $tenEur->allocate(array(1, 1, 1));
assert($part1->equals(Money::EUR(334)));
assert($part2->equals(Money::EUR(333)));
assert($part3->equals(Money::EUR(333)));

$pair = new CurrencyPair(new Currency('EUR'), new Currency('USD'), 1.2500);
$usd = $pair->convert($tenEur);
$this->assertEquals(Money::USD(1250), $usd);

Form integration

You have 3 new form types (under Phil\MoneyBundle\Form\Type namespace):, (*10)

  • CurrencyType : asks for a currency among currencies defined in config.yml
  • MoneyType : asks for an amount and a currency
  • SimpleMoneyType : asks for an amount and sets the currency to the reference currency set in config.yml

Example :, (*11)

use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;

// I create my form
$form = $this->createFormBuilder()
    ->add('name', TextType::class)
    ->add('price', MoneyType::class, [
        'data' => Money::EUR(1000), //EUR 10
    ])
    ->add('save', SubmitType::class)
    ->getForm();

Manipulating the form, (*12)

With MoneyType you can manipulate the form elements with, (*13)

amount_options for the amount field, and currency_options for the currency field, fx if you want to change the label., (*14)

$form = $this->createFormBuilder()
    ->add('price', MoneyType::class, [
        'data' => Money::EUR(1000), //EUR 10
        'amount_options' => array(
            'label' => 'Amount',
        ),
        'currency_options' => array(
            'label' => 'Currency',
        ),
    ])
    ->getForm();

With CurrencyType only currency_options can be used, and with SimpleMoneyType only amount_options can be used., (*15)

Saving Money with Doctrine

Solution 1 : two fields in the database

Note that there are 2 columns in the DB table : $priceAmount and $priceCurrency and only one getter/setter : getPrice and setPrice., (*16)

The get/setPrice methods are dealing with these two columns transparently., (*17)

  • Advantage : your DB is clean and you can do sql sum, group by, sort,... with the amount and the currency in two different columns in your db
  • Disadvantage : it is ugly in the entity.
id;
    }

    /**
     * get Money
     *
     * @return Money
     */
    public function getPrice()
    {
        if (!$this->priceCurrency) {
            return null;
        }
        if (!$this->priceAmount) {
            return new Money(0, new Currency($this->priceCurrency));
        }
        return new Money($this->priceAmount, new Currency($this->priceCurrency));
    }

    /**
     * Set price
     *
     * @param Money $price
     * @return TestMoney
     */
    public function setPrice(Money $price)
    {
        $this->priceAmount = $price->getAmount();
        $this->priceCurrency = $price->getCurrency()->getCode();

        return $this;
    }
}
```


#### Solution 2 : use Doctrine type

There is only one string column in your DB table. The money object is manually serialized by
the new Doctrine type.

1.25€ is serialized in your DB by 'EUR 125'. *This format is stable. It won't change in future releases.*.

The new Doctrine type name is "money".

* Advantage : The entity is easy to create and use
* Disadvantage : it is more difficult to directly request the db in SQL.

```php
id;
    }

    /**
     * get Money
     *
     * @return Money
     */
    public function getPrice()
    {
        return $this->price;
    }

    /**
     * Set price
     *
     * @param Money $price
     * @return TestMoney
     */
    public function setPrice(Money $price)
    {
        $this->price = $price;
        return $this;
    }
}
```

### Conversion manager

Convert an amount into another currency

```php
$pairManager = $this->get("phil_money.pair_manager");
$usd = $pairManager->convert($amount, 'USD');
```

Save a conversion value in a DB

```php
use Money\Money;

$pairManager = $this->get("phil_money.pair_manager");
$pairManager->saveRatio('USD', 1.25); // save in ratio file in CSV
$eur = Money::EUR(100);
$usd = $pairManager->convert($amount, 'USD');
$this->assertEquals(Money::USD(125), $usd);
```

### Money formatter

```php
get('phil_money.formatter.money_formatter');
        $price = new Money(123456789, new Currency('EUR'));

        \Locale::setDefault('fr_FR');
        $formatedPrice = $moneyFormatter->localizedFormatMoney($price);
        // 1 234 567,89 €
        $formatedPrice = $moneyFormatter->localizedFormatMoney($price, 'en');
        // €1,234,567.89
    }
}
```

### Twig integration

```twig
{{ $amount | money_localized_format('fr') }} => 1 234 567,89 €
{{ $amount | money_localized_format('en_US') }} => €1,234,567.89
{{ $amount | money_localized_format }} => depends on your default locale
{{ $amount | money_format }}
{{ $amount | money_as_float }}
{{ $amount | money_get_currency | currency_symbol }}
{{ $amount | money_get_currency | currency_name }}
{{ $amount | money_convert("USD") | money_format }}
{{ $amount | money_format_currency }}
```

### PHP templating integration

```php
format($price) ?></span>
<span class="money">formatCurrencyAsSymbol($price->getCurrency()) ?></span>

Fetching ratio values from remote provider

# save a ratio in the storage
./bin/console phil:money:ratio-save USD 1.25

# display ratio list
./bin/console phil:money:ratio-list

# fetch all the ratio for all defined currencies from an external API
./bin/console phil:money:ratio-fetch

Change the ratio provider

The ratio provider by default is base on the service 'phil_money.ratio_provider.ecb', (*18)

This bundles contains one ratio providers :, (*19)

  • phil_money.ratio_provider.ecb based on the data provided here https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml

You can change the service to use in the config.yml file :, (*20)

phil_money:
    [...]
    ratio_provider: phil_money.ratio_provider.ecb

Additional rate providers from Exchanger

This project integrates https://github.com/florianv/exchanger library to work with currency exchange rates from various services., (*21)

Installation:, (*22)

composer require "florianv/exchanger" "php-http/message" "php-http/guzzle6-adapter", (*23)

Configuration:, (*24)

First, you need to add services you would like to use into your services.yml file, e.g:, (*25)

ratio_provider.service.ecb:
  class: Exchanger\Service\EuropeanCentralBank

Second, you need to update ratio provider used by MoneyBundle on your config.yml file:, (*26)

phil_money:
    [...]
    ratio_provider: ratio_provider.service.ecb

Recommended:, (*27)

Some providers focus on a limited set of currencies, but give better data. You can use several rate providers seamlessly on your project by bundling them into the chain. If some provider does not support certain currency, next provider in the chain would be attempted., (*28)

Example of chained providers:, (*29)

ratio_provider.service.ecb:
  class: Exchanger\Service\EuropeanCentralBank

ratio_provider.service.rcb:
  class: Exchanger\Service\RussianCentralBank

ratio_provider.service.cryptonator:
  class: Exchanger\Service\Cryptonator

ratio_provider.service.array:
  class: Exchanger\Service\PhpArray
  arguments:
    -
      'EUR/USD': 1.157
      'EUR/AUD': 1.628

ratio_provider.service.default:
  class: Exchanger\Service\Chain
  arguments:
    -
      - "@ratio_provider.service.ecb"
      - "@ratio_provider.service.rcb"
      - "@ratio_provider.service.cryptonator"
      - "@ratio_provider.service.array"

As you can see here 4 providers would be attempted one after another until conversion rate is found. Check this page for a fill list of supported services and their configurations: https://github.com/florianv/exchanger/blob/master/doc/readme.md#supported-services, (*30)

And then you need to assign rate provider on your config.yml file:, (*31)

phil_money:
    [...]
    ratio_provider: ratio_provider.service.default

Create your own ratio provider

A ratio provider is a service that implements the Phil\MoneyBundle\Pair\RatioProviderInterface. I recommend that you read the PHP doc of the interface to understand how to implement a new ratio provider., (*32)

The new ratio provider has to be registered as a service., (*33)

To use the new ratio provider, you should set the service to use in the config.yml by giving the service name., (*34)

phil_money:
    [...]
    ratio_provider: phil_money.ratio_provider.google

automatic currency ratio fetch

Add to your crontab :, (*35)

1 0 * * * /my_app_dir/bin/console phil:money:ratio-fetch > /dev/null

MoneyManager : create a money object from a float

Create a money object from a float can be a bit tricky because of rounding issues., (*36)

<?php
$moneyManager = $this->get("phil_money.money_manager");
$money = $moneyManager->createMoneyFromFloat('2.5', 'USD');
$this->assertEquals("USD", $money->getCurrency()->getCode());
$this->assertEquals(250, $money->getAmount());

history of currency ratio with the pairHistoryManager

Doctrine is required to use this feature., (*37)

In order to get the ratio history, you have to enable it in the configuration and to use Doctrine., (*38)

phil_money:
    currencies: ["USD", "EUR"]
    reference_currency: "EUR"
    enable_pair_history: true

Then you can use the service :, (*39)

$pairHistoryManager = $this->get("phil_money.pair_history_manager");
$dt = new \DateTime("2012-07-08 11:14:15.638276");

// returns ratio for at a given date
$ratio = $pairHistoryManager->getRatioAtDate('USD',$dt);

// returns the list of USD ratio (relative to the reference value)
$ratioList = $pairHistoryManager->getRatioHistory('USD',$startDate, $endDate);

Storage

Two storages for storing ratios are available : CSV File, or Doctrine By default, PhilMoneyBundle is configured with CSV File., (*40)

If you want to switch to a Doctrine storage, edit your config.yml, (*41)

phil_money:
    storage: doctrine

Update your database schema :, (*42)

./bin/console doctrine:schema:update --force

With the Doctrine storage, currency ratio will use the default entity manager and will store data inside the phil_money_doctrine_storage_ratios, (*43)

Custom NumberFormatter in MoneyFormatter

The MoneyFormatter::localizedFormatMoney ( service 'phil_money.formatter.money_formatter' ) use the php NumberFormatter class ( http://www.php.net/manual/en/numberformatter.formatcurrency.php ) to format money., (*44)

You can :, (*45)

  • give your own \NumberFormatter instance as a parameter of MoneyFormatter::localizedFormatMoney
  • subclass the MoneyFormatter and rewrite the getDefaultNumberFormater method to set a application wide NumberFormatter

Using the PhilMoneyBundle without Doctrine

You have to disable the pair history service in order to use the PhilMoneyBundle without Doctrine., (*46)

phil_money:
    enable_pair_history: true

Note : you can imagine to code your own PairHistoryManager for MongoDB or Propel, it is very easy to do. Don't hesitate to submit a PR with your code and your tests., (*47)

Optimizations

In your config.yml, you can :, (*48)

  • select the templating engine to use. By default, only Twig is loaded.
  • define the decimals count after a unit (ex : 12.25€ : 2 decimals ; 11.5678€ : 4 decimals)
phil_money:
    currencies: ["USD", "EUR"]
    reference_currency: "EUR"
    decimals: 2
    enable_pair_history: true
    ratio_provider: phil_money.ratio_provider.yahoo_finance

Contributing

  1. Take a look at the list of issues.
  2. Fork
  3. Write a test (for either new feature or bug)
  4. Make a PR

Requirements

  • PHP 8.1.2+
  • Symfony 6.3+

Authors

Philippe Gamache: [ph-il.ca][https://ph-il.ca] Philippe Le Van - kitpages.fr - x : @plv
Thomas Tourlourat - x: @armetiz, (*49)

Status

Stable, (*50)

what is functional:, (*51)

  • integration of the money library
  • configuration parser
  • pairManager
  • Travis CI integration
  • form integration
  • Twig presentation for forms
  • Twig filters
  • commands for ratio creation and ratio display
  • automatic ratio fetch (with 2 ratio providers)
  • history of currency ratio

The Versions

05/10 2016

dev-symfony3-migration

dev-symfony3-migration https://github.com/TheBigBrainsCompany/TbbcMoneyBundle

This is a Symfony2 bundle that integrates the php money library from Mathias Verraes (Fowler pattern): https://github.com/mathiasverraes/money.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Sebastien Lefebvre

currency money conversion fowler

08/04 2016

2.x-dev

2.9999999.9999999.9999999-dev https://github.com/TheBigBrainsCompany/TbbcMoneyBundle

This is a Symfony2 bundle that integrates the php money library from Mathias Verraes (Fowler pattern): https://github.com/mathiasverraes/money.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Sebastien Lefebvre

currency money conversion fowler

19/05 2015

v2.7.1

2.7.1.0 https://github.com/TheBigBrainsCompany/TbbcMoneyBundle

This is a Symfony2 bundle that integrates the php money library from Mathias Verraes (Fowler pattern): https://github.com/mathiasverraes/money.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Sebastien Lefebvre

currency money conversion fowler

27/04 2015

v2.7.0

2.7.0.0 https://github.com/TheBigBrainsCompany/TbbcMoneyBundle

This is a Symfony2 bundle that integrates the php money library from Mathias Verraes (Fowler pattern): https://github.com/mathiasverraes/money.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Sebastien Lefebvre

currency money conversion fowler

09/12 2014

v2.6.0

2.6.0.0 https://github.com/TheBigBrainsCompany/TbbcMoneyBundle

This is a Symfony2 bundle that integrates the php money library from Mathias Verraes (Fowler pattern): https://github.com/mathiasverraes/money.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Sebastien Lefebvre

currency money conversion fowler

16/10 2014

v2.5.0

2.5.0.0 https://github.com/TheBigBrainsCompany/TbbcMoneyBundle

This is a Symfony2 bundle that integrates the php money library from Mathias Verraes (Fowler pattern): https://github.com/mathiasverraes/money.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Sebastien Lefebvre

currency money conversion fowler

25/09 2014

2.4.0

2.4.0.0 https://github.com/TheBigBrainsCompany/TbbcMoneyBundle

This is a Symfony2 bundle that integrates the php money library from Mathias Verraes (Fowler pattern): https://github.com/mathiasverraes/money.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Sebastien Lefebvre

currency money conversion fowler

16/07 2014

v2.3.1

2.3.1.0 https://github.com/TheBigBrainsCompany/TbbcMoneyBundle

This is a Symfony2 bundle that integrates the php money library from Mathias Verraes (Fowler pattern): https://github.com/mathiasverraes/money.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Sebastien Lefebvre

currency money conversion fowler

11/07 2014

v2.3.0

2.3.0.0 https://github.com/TheBigBrainsCompany/TbbcMoneyBundle

This is a Symfony2 bundle that integrates the php money library from Mathias Verraes (Fowler pattern): https://github.com/mathiasverraes/money.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Sebastien Lefebvre

currency money conversion fowler

11/07 2014
02/06 2014
01/02 2014
18/12 2013
17/12 2013
26/07 2013

v1.4.0

1.4.0.0 https://github.com/TheBigBrainsCompany/TbbcMoneyBundle

This is a Symfony2 bundle that integrates the php money library (Fowler pattern): https://github.com/mathiasverraes/money.

  Sources   Download

BSD

The Requires

 

The Development Requires

by Sebastien Lefebvre

currency money conversion fowler

16/07 2013

v1.3.0

1.3.0.0 https://github.com/TheBigBrainsCompany/TbbcMoneyBundle

This is a Symfony2 bundle that integrates the php money library (Fowler pattern): https://github.com/mathiasverraes/money.

  Sources   Download

BSD

The Requires

 

The Development Requires

by Sebastien Lefebvre

currency money conversion fowler

12/07 2013

v1.2.0

1.2.0.0 https://github.com/TheBigBrainsCompany/TbbcMoneyBundle

This is a Symfony2 bundle that integrates the php money library (Fowler pattern): https://github.com/mathiasverraes/money.

  Sources   Download

BSD

The Requires

 

The Development Requires

by Sebastien Lefebvre

currency money conversion fowler

04/07 2013

v1.1.0

1.1.0.0 https://github.com/TheBigBrainsCompany/TbbcMoneyBundle

This is a Symfony2 bundle that integrates the php money library (Fowler pattern): https://github.com/mathiasverraes/money.

  Sources   Download

BSD

The Requires

 

The Development Requires

by Sebastien Lefebvre

currency money conversion fowler

03/07 2013

v1.0.0

1.0.0.0 https://github.com/TheBigBrainsCompany/TbbcMoneyBundle

This is a Symfony2 bundle that integrates the php money library (Fowler pattern): https://github.com/mathiasverraes/money.

  Sources   Download

BSD

The Requires

 

The Development Requires

by Sebastien Lefebvre

currency money conversion fowler