Werken met Nederlands prijzen in Laravel
Een artikel hoe te werken met Nederlandse prijzen / bedragen in Laravel. Opslaan doe ik als dicimaal database veld maar (eind) gebruikers voeren niet 19.95, maar 19,95. Het tonen van de prijs is natuurlijk ook gebruikelijk met een komma.
Je zou bij het opslaan de komma kunnen veranderen naar een punt en weer bij het tonen, de punt veranderen in een komma. Alleen moet je dit bij elke plek bij het tonen en opslaan doen. Gelukkig heeft Laravel mutators en accessors. Je kan het volgende in je model zetten die een prijs bevat.
/**
* Mutator for price: convert comma to dot when saving.
*
* @param mixed $value
*
* @return void
*/
public function setPriceAttribute($value)
{
$this->attributes['price'] = is_string($value) ? str_replace(',', '.', $value) : $value;
}
/**
* Accessor for price: convert dot to comma when retrieving.
*
* @param mixed $value
*
* @return string|null
*/
public function getPriceAttribute($value)
{
return is_numeric($value) ? str_replace('.', ',', $value) : $value;
}
Nu kan je overal php $model->price tonen zonder de punt naar een komma te hoeven omzetten.
Form validate
Bij het opslaan wil je kijken of geen komma (hele bedragen) of de prijs een komma bevat en maximaal 2 decimalen. Laravel heeft hier geen standaard form validatie voor maar je kan wel een regexp gebruiken.
'price' => ['nullable', '/^\d+([.,]\d{1,2})?$/']
Het nadeel is alleen, als je met veel prijs velden werkt je deze regexp elke keer moet zetten (en waarschijnlijk eerst moet opzoeken ;) Gelukkig heeft Laravel hier ook iets moois voor, custom Rules.
Je kan met een artisan een custom rule aanmaken:
php artisan make:rule PriceFormatRule
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class AmountRule implements Rule
{
public function __construct()
{
}
public function passes($attribute, $value): bool
{
return preg_match('/^\d+([.,]\d{1,2})?$/', trim($value));
}
public function message(): string
{
return 'Het veld :attribute moet een getal bevatten met één punt of komma en maximaal 2 cijfers erachter.';
}
}
Nu kan je overal deze custum validate rule gebruiken.
'price' => ['nullable', new PriceFormatRule()]