Installation:
composer require babdev/money-bundle
Enable the bundle in config/bundles.php:
return [
// ...
BabDev\MoneyBundle\MoneyBundle::class => ['all' => true],
];
Configure Default Currency (optional):
# config/packages/babdev_money.yaml
babdev_money:
default_currency: EUR # Defaults to USD
First Use Case:
Create a Money object in a controller:
use Money\Money;
$price = Money::EUR(1000); // 10.00 EUR (amount in cents)
return $this->json(['price' => $price]);
Doctrine Integration:
#[ORM\Embedded] for Money fields in entities:
#[ORM\Entity]
class Product {
#[ORM\Embedded(class: Money::class)]
public Money $price;
}
#[ODM\EmbedOne]:
#[ODM\Document]
class Product {
#[ODM\EmbedOne(targetDocument: Money::class)]
public Money $price;
}
Form Handling:
MoneyType form field:
use BabDev\MoneyBundle\Form\Type\MoneyType;
$builder->add('price', MoneyType::class, [
'currency' => 'EUR',
'required' => true,
]);
Validation:
Money fields:
use BabDev\MoneyBundle\Validator\Constraints\MoneyGreaterThan;
#[MoneyGreaterThan(value: 0)]
public Money $price;
Twig Integration:
Money in templates:
{{ product.price|money('decimal', 'en_US', {fraction_digits: 2}) }}
Money objects dynamically:
{% set discount = money(500, 'EUR') %}
API Serialization:
Money to JSON:
{
"price": {
"amount": "1000",
"currency": "EUR"
}
}
MoneyFormatter and register them in Twig:
$twig->addFunction(new \Twig\TwigFunction('custom_money', function ($money) {
return (new CustomMoneyFormatter())->format($money);
}));
Money\Currency and Money\Converter for dynamic conversions:
$converter = new Money\Converter(new Money\CurrencyCollection());
$converter->convert(Money::USD(1000), 'EUR');
Amount Precision:
Money objects store amounts in cents (e.g., 1000 = 10.00 EUR). Ensure your application logic accounts for this (e.g., avoid floating-point arithmetic).Money::USD(1000)->getAmount() to get raw cents.Doctrine Type Mismatches:
Money fields are mapped as embedded (not column). MongoDB ODM handles this automatically.#[ORM\Embedded(class: Money::class)] to your entity properties.Serializer Conflicts:
JMSSerializerBundle is installed and configured. The Symfony Serializer works out-of-the-box.composer require jms/serializer-bundle
Twig Filter Limitations:
money filter does not support the aggregate formatter from MoneyPHP. Use intl_money or decimal instead.Money objects in PHP if custom formatting is needed.Validation Groups:
MoneyGreaterThan) require explicit validation groups if used in forms or DTOs.groups: ['validation'] to your constraint options.US instead of USD) will throw exceptions. Validate against ISO 4217.var_dump() or dd() to inspect serialized Money objects:
$serializer->serialize($money, 'json');
Money objects fail to serialize/deserialize, ensure Doctrine proxies are disabled for embedded objects:
# config/packages/doctrine.yaml
doctrine:
orm:
entity_managers:
default:
metadata_driver:
orm:
mappings:
App:
type: attribute
is_bundle: false
dir: "%kernel.project_dir%/src/Entity"
prefix: "App\Entity"
alias: App
dql:
string_functions:
CONCAT: DoctrineExtensions\Query\Mysql\Concat
Custom Validators:
MoneyAssert constraints by creating a new validator class:
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class CustomMoneyValidator extends ConstraintValidator {
public function validate($value, Constraint $constraint) {
if (!$value instanceof Money\Money) {
$this->context->buildViolation($constraint->message)
->addViolation();
}
}
}
services:
App\Validator\CustomMoneyValidator:
tags: [validator.constraint_validator]
Dynamic Currency Switching:
use BabDev\MoneyBundle\Money\MoneyService;
public function __construct(private MoneyService $moneyService) {}
public function handle(Request $request, callable $next) {
$this->moneyService->setDefaultCurrency('EUR'); // Override for request
return $next($request);
}
Monetary Calculations:
use Money\Money;
class MoneyCalculator {
public function applyDiscount(Money $price, float $percentage): Money {
$discountAmount = $price->multiply($percentage / 100);
return $price->subtract($discountAmount);
}
}
How can I help you explore Laravel packages today?