0

I developing system where money is basic thing, for now to show any price i am using accessors in model:

public function getFormattedPriceAttribute()
{
    return '$' . number_format($this->attributes['price'], 2); // TODO: implement currencies
}

But soon I will start implementing multicurrency and i want to make price showing as easy as define:

protected $casts = [
'price' => 'currency',
];

And custom cast for currency will format it as set in configuration.

Is this possible withot dancing with a tambourine?

2
  • 1
    I think a bit of a dance with tambourine is going to make your life much easier in the long run. I would create a separate class for managing Currency (with methods like 'eur', 'dollar', 'formatted' ... whatever you need) and cast all price attributes to this class (which would take value as constructor). Then you could do things like $model->price->eur or $model->price->formatted. Commented Feb 6, 2017 at 16:01
  • just a tip: php.net/manual/en/function.money-format.php Commented Feb 6, 2017 at 18:27

1 Answer 1

3

Expanding on my comment:

Cool

I would create a Currency class, something like this:

class Currency {
    $value;

    public function __construct($value) 
    {
        $this->value = $value;
    }

    public function formatted()
    {
        return '$' . number_format($this->value, 2);
    }

    // more methods

}

Then override the Model castAttribute methods, to include the new castable class:

protected function castAttribute($key, $value)
{
    if (is_null($value)) {
        return $value;
    }

    switch ($this->getCastType($key)) {
        case 'int':
        case 'integer':
            return (int) $value;
        case 'real':
        case 'float':
        case 'double':
            return (float) $value;
        case 'string':
            return (string) $value;
        case 'bool':
        case 'boolean':
            return (bool) $value;
        case 'object':
            return $this->fromJson($value, true);
        case 'array':
        case 'json':
            return $this->fromJson($value);
        case 'collection':
            return new BaseCollection($this->fromJson($value));
        case 'date':
        case 'datetime':
            return $this->asDateTime($value);
        case 'timestamp':
            return $this->asTimeStamp($value);

        case 'currency': // Look here
            return Currency($value);
        default:
            return $value;
    }
}

Simple

Of course you could make things much simpler and just do this in the castAttribute method:

// ...
case 'dollar':
    return  '$' . number_format($value, 2);
// ...
Sign up to request clarification or add additional context in comments.

3 Comments

So, for now no way to "Inject" custom cast type to casts list?
Yeah simple and easy. The only thing is that you'll have to have this bloated method in the model, which is not nice. You could make it into a trait maybe.
I think, I will try to fork and make casting capsulated, when wil have free time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.