• Stars
    star
    153
  • Rank 243,368 (Top 5 %)
  • Language
    PHP
  • License
    MIT License
  • Created about 4 years ago
  • Updated 9 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A Laravel package that makes working with money in a secure manner a cinch!

Mula

Latest Version on Packagist Mula PhpUnit Tests Quality Score

Mula is a Laravel package that makes it super easy to work with money in your applications. It uses Money for PHP under the hood, but takes away all the complexity and provides all the pieces you need to be up and running with money in a matter of minutes.

Mula is also fully immutable, so you won't run in to issues changing values you really wish you hadn't. It also handles rounding and allocation, so you don't have to worry about any finances going missing.

TOC

Installation

You can install the package via composer:

composer require lukeraymonddowning/mula

You should publish the mula.php config file by running:

php artisan vendor:publish --provider="Lukeraymonddowning\Mula\MulaServiceProvider"

Basic usage and API

We provide a Mula facade that allows you to easily create, parse and alter monetary values.

Create

To manually create a new instance, use the create method.

Mula::create('12000', 'USD'); // $120.00

Note that when creating, we exclude any decimal point. Currency should be passed as an ISO 4217 code.

You may also exclude the currency, in which case Mula will use the default currency defined in the mula.php config file, or your .env file using the MULA_CURRENCY key.

Whilst we will use strings to pass values to the create method in the documentation, you are free to pass integer values instead.

Parse

More often than not, you'll want to parse existing monetary values rather than create new ones from scratch. You should use the parse method when handling user input or reading monetary values from a 3rd party API.

If you are using the phpmoney driver (which is the default), you have a few different drivers you can use for parsing money. You can set your desired driver in the mula.php config file, by altering the value of mula.options.phpmoney.parser.default.

We recommend using the default aggregate parser, but for the sake of clarity, we'll explain the difference between each one.

Whilst we will use strings to pass values to the parse method in the documentation, you are free to pass integers or decimal values instead.

Aggregate

The aggregate parser (which is the default) is the most flexible driver available, and will attempt to parse monetary strings formatted in international or decimal. Here are a few examples:

Mula::parse('$120.99'); // $120.99

Mula::parse('120.99', 'USD'); // $120.99

Mula::parse('ยฃ120.99', 'USD'); // $120.99

Mula::parse('120', 'USD'); // $120.00

Note that in the third example, the money object is in USD, even though we parsed a value in GBP. That is because we passed a second parameter of USD. Passing in a currency will always override the given currency.

International

The international parser will parse full monetary string with currency, but will not parse decimal strings.

Mula::parse('$120.99'); // $120.99

Mula::parse('120.99'); // Exception

Decimal

The decimal parser will parse decimal values with the given currency (or the default currency), but will not parse monetary strings.

Mula::parse('120.99', 'USD'); // $120.99

Mula::parse('$120.99'); // Exception

Display

To display money in the UI, you can use the display method. It accepts a single parameter, includeCurrency, which will either include or omit the currency symbol from the result.

Mula::create('12099', 'USD')->display(); // $120.99

Mula::create('12099', 'USD')->display(false); // 120.99

Mula also implements the Stringable interface, so you can output money directly in a blade view.

@php($money = Mula::create('12099', 'USD'))
<span>{{ $money }}</span>

{-- This will show as '$120.99' --}

Display without currency

As a syntactical nicety, you may use the displayWithoutCurrency method, which is just an alias for display(false).

Currency

The currency method will return the ISO 4217 code of the money object.

Mula::create('12099', 'USD')->currency(); // USD

Mula::create('12099', 'GBP')->currency(); // GBP

Value

The value method will return the nonformatted value of the money object. You will rarely need to use this method, but Mula makes use of it for casting values to the database.

Mula::create('12099', 'USD')->value(); // 12099

Add

The add method adds the provided money objects to the current money object and returns a new money object. You may pass any number of money objects as varadic parameters.

Mula::create('1500', 'USD')->add(Mula::create('1500', 'USD'))->display(); // $30.00

Mula::create('1500', 'USD')->add(Mula::create('1500', 'USD'), Mula::create('3000', 'USD'))->display(); // $60.00

Subtract

The subtract method subtracts the provided money objects from the current money object and returns a new money object. You may pass any number of money objects as varadic parameters.

Mula::create('3000', 'USD')->subtract(Mula::create('1500', 'USD'))->display(); // $15.00

Mula::create('6000', 'USD')->subtract(Mula::create('1500', 'USD'), Mula::create('3000', 'USD'))->display(); // $15.00

Multiply by

The multiplyBy method multiplies the money object by the given multiplier and returns a new money object.

Mula::create('5000', 'USD')->multiplyBy(2)->display(); // $100.00

Divide by

The divideBy method divides the money object by the given divisor and returns a new money object.

Mula::create('5000', 'USD')->divideBy(2)->display(); // $25.00

Modulus

The mod method returns the remainder of money after being divided into another sum of money.

Mula::create('1000', 'USD')->mod(Mula::create('300', 'USD'))->display(); // $1.00

Has same currency as

To check if a money object has the same currency as other money objects, use the hasSameCurrencyAs method. It accepts a variable number of money objects as arguments. If any of the arguments have a different currency, the method will return false, otherwise it will return true.

Mula::create('1000', 'USD')->hasSameCurrencyAs(Mula::create('500', 'USD')); // TRUE

Mula::create('1000', 'USD')->hasSameCurrencyAs(Mula::create('500', 'GBP')); // FALSE

Mula::create('1000', 'USD')->hasSameCurrencyAs(Mula::create('500', 'USD'), Mula::create('3000', 'USD')); // TRUE

Mula::create('1000', 'USD')->hasSameCurrencyAs(Mula::create('500', 'USD'), Mula::create('3000', 'GBP')); // FALSE

Equals

To check if a money object is equal to other money objects, use the equals method. It accepts a variable number of money objects as arguments. If any of the arguments have a different amount, the method will return false, otherwise it will return true.

Mula::create('1000', 'USD')->equals(Mula::create('1000', 'USD')); // TRUE

Mula::create('1000', 'USD')->equals(Mula::create('500', 'USD')); // FALSE

Mula::create('1000', 'USD')->equals(Mula::create('1000', 'USD'), Mula::create('1000', 'USD')); // TRUE

Mula::create('1000', 'USD')->equals(Mula::create('1000', 'USD'), Mula::create('500', 'USD')); // FALSE

Is greater than

The isGreaterThan method checks if a money object is greater than all other money objects. It returns true if it is, or false if any of the money object provided are greater than or equal to it.

Mula::create('1000', 'USD')->isGreaterThan(Mula::create('999', 'USD')); // TRUE

Mula::create('1000', 'USD')->isGreaterThan(Mula::create('1000', 'USD')); // FALSE

Mula::create('1000', 'USD')->isGreaterThan(Mula::create('1500', 'USD')); // FALSE

Mula::create('1000', 'USD')->isGreaterThan(Mula::create('999', 'USD'), Mula::create('800', 'USD')); // TRUE

Mula::create('1000', 'USD')->isGreaterThan(Mula::create('1000', 'USD'), Mula::create('500', 'USD')); // FALSE

Is greater than or equal to

The isGreaterThanOrEqualTo method checks if a money object is greater than or equal to all other money objects. It returns true if it is, or false if any of the money object provided are greater than it.

Mula::create('1000', 'USD')->isGreaterThanOrEqualTo(Mula::create('999', 'USD')); // TRUE

Mula::create('1000', 'USD')->isGreaterThanOrEqualTo(Mula::create('1000', 'USD')); // TRUE

Mula::create('1000', 'USD')->isGreaterThanOrEqualTo(Mula::create('1500', 'USD')); // FALSE

Mula::create('1000', 'USD')->isGreaterThanOrEqualTo(Mula::create('999', 'USD'), Mula::create('800', 'USD')); // TRUE

Mula::create('1000', 'USD')->isGreaterThanOrEqualTo(Mula::create('1000', 'USD'), Mula::create('500', 'USD')); // TRUE

Mula::create('1000', 'USD')->isGreaterThanOrEqualTo(Mula::create('1000', 'USD'), Mula::create('1500', 'USD')); // FALSE

Is less than

The isLessThan method checks if a money object is less than all other money objects. It returns true if it is, or false if any of the money object provided are less than or equal to it.

Mula::create('1000', 'USD')->isLessThan(Mula::create('999', 'USD')); // FALSE

Mula::create('1000', 'USD')->isLessThan(Mula::create('1000', 'USD')); // TRUE

Mula::create('1000', 'USD')->isLessThan(Mula::create('1500', 'USD')); // TRUE

Mula::create('1000', 'USD')->isLessThan(Mula::create('1500', 'USD'), Mula::create('800', 'USD')); // FALSE

Mula::create('1000', 'USD')->isLessThan(Mula::create('1200', 'USD'), Mula::create('1500', 'USD')); // TRUE

Is less than or equal to

The isLessThanOrEqualTo method checks if a money object is less than or equal to all other money objects. It returns true if it is, or false if any of the money object provided are less than it.

Mula::create('1000', 'USD')->isLessThanOrEqualTo(Mula::create('999', 'USD')); // FALSE

Mula::create('1000', 'USD')->isLessThanOrEqualTo(Mula::create('1000', 'USD')); // TRUE

Mula::create('1000', 'USD')->isLessThanOrEqualTo(Mula::create('1500', 'USD')); // TRUE

Mula::create('1000', 'USD')->isLessThanOrEqualTo(Mula::create('999', 'USD'), Mula::create('800', 'USD')); // FALSE

Mula::create('1000', 'USD')->isLessThanOrEqualTo(Mula::create('1000', 'USD'), Mula::create('500', 'USD')); // FALSE

Mula::create('1000', 'USD')->isLessThanOrEqualTo(Mula::create('1000', 'USD'), Mula::create('1500', 'USD')); // TRUE

Split

Split is rather special. It allocates money based on the provided allocation. It can accept an integer, array or Collection and returns a Collection of Money.

If you want to split a money object as evenly as possible between a given number, pass an integer.

Mula::create('10000', 'USD')->split(3); // A Collection. The first item will have a value of $33.34 the second and third items will have a value of $33.33. 

If you want to allocate money based on percentages, you may pass an array or Collection of numeric values. The values must add up to 100.

Mula::create('10000', 'USD')->split([30, 70]); // A Collection. The first item will have a value of $30.00 and the second item will have a value of $70.00.

Mula::create('10000', 'USD')->split(collect([30, 70])); // A Collection. The first item will have a value of $30.00 and the second item will have a value of $70.00.

Storing money in a database

Mula makes it easy to store and retrieve money values from a database by providing a custom cast you can attach to your Eloquent models.

use Illuminate\Database\Eloquent\Model;
use Lukeraymonddowning\Mula\Casts\Mula;

class Product extends Model {

    protected $casts = [
        'price' => Mula::class
    ];

}

The column storing your monetary values in your database should be a string type. This prevents floating point errors and also allows Mula to store the currency along with the value.

If you'd prefer to store your amount and currency in two separate columns, which allows you more freedom when performing database queries, you can! Just let Mula know the amount column and currency column respectively in your $casts array.

use Illuminate\Database\Eloquent\Model;
use Lukeraymonddowning\Mula\Casts\Mula;

class Product extends Model {

    protected $casts = [
        'price' => Mula::class.':amount,currency'
    ];

}

Collection methods

Mula adds macros to Laravel Collections to make it easy to perform common monetary operations to a Collection of money objects.

Financial sum

If you need to add together a Collection of money objects, you may use the financialSum method. It will return a new money object.

collect(Mula::create('1500', 'USD'), Mula::create('3000', 'USD'))->financialSum(); // A new money object with a value of $45.00.

Testing

Mula uses PhpUnit for unit tests. You can run the test suite from the terminal:

composer test

Changelog

Please see CHANGELOG for more information what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

Laravel Package Boilerplate

This package was generated using the Laravel Package Boilerplate.

More Repositories

1

whenipress

A tiny, powerful and declarative wrapper around keyboard bindings in JavaScript
JavaScript
481
star
2

honey

A spam prevention package for Laravel, providing honeypot techniques, ip blocking and beautifully simple Recaptcha integration. Stop spam. Use Honey.
PHP
407
star
3

poser

Create class based model factories in Laravel applications in seconds.
PHP
277
star
4

MountainBreeze

A Wordpress theme starter template for the modern web developer, including Tailwind CSS, Alpine JS and Laravel Blade
PHP
163
star
5

self-healing-urls

A Laravel package that allows you to define self-healing URLs for Eloquent models
PHP
158
star
6

alpinimations

Streamline your animations by using these simple blade directives in your components!
Blade
101
star
7

laravel-template

An opinionated Laravel setup using my favourite tools
PHP
59
star
8

actions-are-a-devs-best-friend

Talk codebase
PHP
26
star
9

pest-plugin-money

A plugin for working with popular money libraries in Pest
PHP
19
star
10

Tupper

A simple, no-nonsense IoC Container written in PHP for Dependency Injection
PHP
13
star
11

nightguard

Set up Laravel Auth guards using Eloquent in seconds
PHP
11
star
12

pest-plugin-larastrap

Wraps your Pest suite in a Laravel application instance, allowing global use of the framework in tests.
PHP
9
star
13

uniquestyles

PostCSS plugin that strips selectors found in other stylesheets.
JavaScript
9
star
14

laracasts-pest-from-scratch

PHP
5
star
15

infinite_scrolling_in_inertia_js

PHP
3
star
16

laravel_nova_mastery_2023

The Source Code for the Laravel Nova Mastery 2023 Series
PHP
3
star
17

stubble

A templating engine for Laravel stub files
PHP
2
star
18

valid-variants-of-validating-validation

The presentation, code and resources for the talk "Valid Variants of Validating Validation"
PHP
2
star
19

migrating-from-mix-to-vite

JavaScript
2
star
20

blog-2

My personal blog
PHP
2
star
21

laravel-erp-crm

A Laravel ERP Module providing CRM functionality
PHP
1
star
22

syndicate

A simple way to add companies, organisations and groups to your Laravel project.
PHP
1
star
23

plug-in-play

PHP
1
star
24

laravel-address-lookup

Allows you to use many different services to find an address based on a postal code.
PHP
1
star
25

blog

My personal blog
PHP
1
star