coverd/money-bundle

此包已被废弃,不再维护。未建议替换包。

这是一个整合了 moneyphp/money 库(Fowler 模式)的 Symfony 扩展包:https://github.com/moneyphp/money。

安装: 20,135

依赖项: 0

建议者: 0

安全: 0

星标: 3

关注者: 7

分支: 0

开放问题: 0

类型:symfony-bundle

v1.3.0 2021-12-07 13:52 UTC

This package is auto-updated.

Last update: 2022-09-07 15:30:18 UTC


README

Latest Version Build Status

免责声明

原始包为 TbbcMoneyBundle。由于此仓库维护不足,我们进行了分支并大量简化,移除了所有不必要的功能(基本上,与对/比相关的所有功能)。

描述

此包用于将 mathiasverraes 的 Money 库整合到 Symfony 项目中。

该库基于 Fowler 的 Money 模式

特性

  • 整合 mathiasverraes 的 money 库
  • 模板中用于货币和货币单位的 Twig 过滤器和 PHP 辅助函数
  • Symfony 表单集成
  • 用于指定网站使用的货币的配置解析器
  • 货币格式化国际化

安装

使用 Composer 并使用 composer require coverd/money-bundle 安装

配置包(配置文件应位于 config/packages/coverd_money.yml 中)

coverd_money:
    currencies: ["USD", "EUR"] # Choose all availables currencies
    reference_currency: "EUR" # Choose the default currency
    decimals: 2 # Choose the number of decimals (default: 2)

使用 twig 表单主题

twig:
    form_themes:
        - 'MoneyBundle:Form:fields.html.twig'

注册 Doctrine Money 类型

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

用法

Money 库集成

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)));

表单集成

你有 3 种新的表单类型(位于 Coverd\MoneyBundle\Form\Type 命名空间下)

  • CurrencyType:要求选择在 config.yml 中定义的货币之一
  • MoneyType:要求输入金额和货币
  • SimpleMoneyType:要求输入金额,并将货币设置为 config.yml 中设置的参考货币

示例

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),
    ])
    ->getForm();

操作表单

使用 MoneyType,您可以使用以下方式操作表单元素:

amount_options 用于金额字段,currency_options 用于货币字段,例如,如果您想更改标签。

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

使用 CurrencyType 只能使用 currency_options,使用 SimpleMoneyType 只能使用 amount_options

使用 Doctrine 保存货币

解决方案 1:数据库中的两个字段

请注意,数据库表中有两列:$priceAmount 和 $priceCurrency,只有一个 getter/setter:getPrice 和 setPrice。

get/setPrice 方法透明地处理这两列。

  • 优势:您的数据库干净,您可以在数据库的两个不同列中使用数量和货币进行SQL求和、分组、排序等操作
  • 劣势:在实体中看起来比较丑。
<?php
namespace App\AdministratorBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Money\Currency;
use Money\Money;

/**
 * @ORM\Table("test_money")
 * @ORM\Entity
 */
class TestMoney
{
    /**
     * @var integer
     *
     * @ORM\Column(name="price_amount", type="integer")
     */
    private $priceAmount;

    /**
     * @var string
     *
     * @ORM\Column(name="price_currency", type="string", length=64)
     */
    private $priceCurrency;

    public function getPrice(): Money
    {
        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));
    }

    public function setPrice(Money $price): void
    {
        $this->priceAmount = $price->getAmount();
        $this->priceCurrency = $price->getCurrency()->getCode();
    }
}

解决方案2:使用Doctrine类型

您的数据库表只有一个字符串列。货币对象通过新的Doctrine类型手动序列化。

1.25欧元在数据库中序列化为'EUR 125'。 此格式是稳定的。未来版本中不会更改。

新的Doctrine类型名称为"money"。

  • 优势:实体易于创建和使用
  • 劣势:直接在SQL中请求数据库更为困难。
<?php
namespace App\AdministratorBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Money\Money;

/**
 * @ORM\Table("test_money")
 * @ORM\Entity
 */
class TestMoney
{
    /**
     * @var Money
     *
     * @ORM\Column(name="price", type="money")
     */
    private $price;

    public function getPrice(): Money
    {
        return $this->price;
    }

    public function setPrice(Money $price): void
    {
        $this->price = $price;
    }
}

货币格式化器

<?php

namespace My\Controller\IndexController;

use Money\Money;
use Money\Currency;

class IndexController extends Controller
{
    public function myAction()
    {
        $moneyFormatter = $this->get('coverd_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

        // old method (before v2.2)
        $formattedPrice = $moneyFormatter->formatMoney($price); // 1 234 567,89

        $formattedCurrency = $moneyFormatter->formatCurrency($price); // €
    }
}

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.currency | currency_symbol }}
{{ $amount | money_format_currency }}

MoneyManager:从浮点数创建货币对象

从浮点数创建货币对象可能有些棘手,因为存在舍入问题。

<?php

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

在MoneyFormatter中自定义NumberFormatter

MoneyFormatter::localizedFormatMoney(服务'coverd_money.formatter.money_formatter')使用php NumberFormatter类(https://php.ac.cn/manual/en/numberformatter.formatcurrency.php)来格式化货币。

您可以将

  • 自己的\NumberFormatter实例作为MoneyFormatter::localizedFormatMoney的参数
  • 继承MoneyFormatter并重写getDefaultNumberFormater方法来设置应用程序范围的NumberFormatter