Installation
composer require coverd/money-bundle
Add to config/bundles.php:
return [
// ...
Coverd\MoneyBundle\CoverdMoneyBundle::class => ['all' => true],
];
Basic Configuration
Edit config/packages/coverd_money.yaml:
coverd_money:
default_currency: 'EUR'
currencies: ['EUR', 'USD', 'GBP']
First Use Case Create a money value in a controller or service:
use Money\Money;
use Money\Currency;
$amount = 100; // 100 cents (or 1.00 EUR)
$currency = new Currency('EUR');
$money = new Money($amount, $currency);
// Or use the bundle's helper:
$money = $this->get('coverd_money.factory')->create($amount, 'EUR');
Money Creation Use the factory service for consistency:
$factory = $this->get('coverd_money.factory');
$money = $factory->create(100, 'USD'); // 1.00 USD
Currency Conversion
Inject the Coverd\MoneyBundle\Service\CurrencyConverter:
$converter = $this->get('coverd_money.converter');
$converted = $converter->convert($money, 'GBP'); // Converts to GBP
Validation Validate money in forms using Symfony’s validator:
# config/validator/validation.yaml
Coverd\MoneyBundle\Validator\Constraints\Money:
currency: EUR
min: 0
max: 100000
Database Storage Store as cents (integer) + currency (string):
$money->getAmount(); // 100 (cents)
$money->getCurrency()->getCode(); // 'EUR'
Twig Integration
Use the money filter:
{{ money(100, 'EUR') }} → "1.00 €"
MoneyType for entities:
use Coverd\MoneyBundle\Doctrine\Types\MoneyType;
/**
* @ORM\Column(type="money")
*/
private $price;
MoneyJsonEncoder:
$encoder = $this->get('coverd_money.json_encoder');
$json = $encoder->encode($money, 'json');
MoneyCommand for CLI tools:
$this->get('coverd_money.command')->process($money);
Precision Handling
100 = 1.00 EUR, not 1.00 (which could become 0.999999).Currency Codes
USD, not US$).config/packages/coverd_money.yaml currencies.Converter Dependencies
Symfony 6+ Compatibility
moneyphp/money is ^3.0. The bundle may lag behind.Doctrine Migrations
MoneyType, run:
php bin/console doctrine:migrations:diff
dump($money->getAmount(), $money->getCurrency()->getCode());
$converter->getRate('EUR', 'USD'); // Returns null if no rate set
# config/packages/validator.yaml
Coverd\MoneyBundle\Validator\Constraints\Money:
message: "The amount must be between {{ min }} and {{ max }} {{ currency }}."
Custom Converter
Extend Coverd\MoneyBundle\Service\CurrencyConverter to fetch rates from an API:
class ApiCurrencyConverter extends CurrencyConverter {
public function getRate(string $from, string $to): ?float {
$response = HttpClient::create()->request('GET', 'https://api.exchangerate-api.com/v4/latest/'.$from);
return $response->toArray()['rates'][$to] ?? null;
}
}
Register as a service:
services:
coverd_money.converter:
class: App\Service\ApiCurrencyConverter
Custom Money Type
Override MoneyType for custom storage (e.g., JSON):
class JsonMoneyType extends MoneyType {
public function convertToDatabaseValue($value, AbstractPlatform $platform) {
return json_encode([
'amount' => $value->getAmount(),
'currency' => $value->getCurrency()->getCode(),
]);
}
}
Event Listeners
Listen to coverd_money.pre_convert to modify conversions:
$eventDispatcher->addListener('coverd_money.pre_convert', function (PreConvertEvent $event) {
if ($event->getFrom()->getCurrency()->getCode() === 'EUR') {
$event->setRate(1.1); // Force USD rate
}
});
Testing
Use MoneyTestCase for assertions:
use Coverd\MoneyBundle\Tests\MoneyTestCase;
class MyTest extends MoneyTestCase {
public function testMoneyCreation() {
$this->assertMoneyEquals(new Money(100, new Currency('EUR')), '100 EUR');
}
}
How can I help you explore Laravel packages today?