A simple PHP library for complex monetary prices management

Overview

PHP Prices

💸 Version 2.x

This new major version is shifting the package towards more flexibility and configuration possibilities in general.

One of the main differences is that we replaced moneyphp/money with brick/money under the hood. This introduces a ton of breaking changes, mainly on the instantiation methods that now reflect brick/money's API in order to keep things developer friendly. The 1.x branch will still be available and maintained for a while, but we strongly recommend updating to 2.x.

Using the underlying brick/money library, this simple Price object allows to work with complex composite monetary values which include exclusive, inclusive, VAT (and other potential taxes) and discount amounts. It makes it safer and easier to compute final displayable prices without having to worry about their construction.

Install

composer require whitecube/php-prices

Getting started

Each Price object has a Brick\Money\Money instance which is considered to be the item's unchanged, per-unit & exclusive amount. All the composition operations, such as adding VAT or applying discounts, are added on top of this base value.

use Whitecube\Price\Price;

$steak = Price::EUR(1850)   // Steak costs €18.50/kg
    ->setUnits(1.476)       // Customer had 1.476kg, excl. total is €27.31
    ->setVat(6)             // There is 6% VAT, incl. total is €28.95
    ->addTax(50)            // There also is a €0.50/kg tax (before VAT), incl. total is €29.73
    ->addDiscount(-100);    // We granted a €1.00/kg discount (before VAT), incl. total is €28.16

It is common practice and always best to work with amounts represented in the smallest currency unit (minor values) such as "cents".

There are several convenient ways to obtain a Price instance:

Method Using major values Using minor values Defining units
Constructor new Price(Money $base) new Price(Money $base) new Price(Money $base, $units)
Brick/Money API Price::of($major, $currency) Price::ofMinor($minor, $currency) -
Currency API - Price::EUR($minor) Price::USD($minor, $units)
Parsed strings Price::parse($value, $currency) - Price::parse($value, $currency, $units)

From Constructor

You can set this basic value by instantiating the Price directly with the desired Brick\Money\Money instance:

use Brick\Money\Money;
use Whitecube\Price\Price;

$base = new Money::ofMinor(500, 'USD');         // $5.00

$single = new Price($base);                     // 1 x $5.00
$multiple = new Price($base, 4);                // 4 x $5.00

From Brick/Money-like methods

For convenience, it is also possible to use the shorthand Money factory methods:

use Whitecube\Price\Price;

$major = Price::of(5, 'EUR');                   // 1 x €5.00
$minor = Price::ofMinor(500, 'USD');            // 1 x $5.00

Using these static calls, you cannot define quantities or units directly with the constructor methods.

For more information on all the available Brick/Money constructors, please take a look at their documentation.

From currency-code methods

You can also create an instance directly with the intended currency and quantities using the 3-letter currency ISO codes:

use Whitecube\Price\Price;

$single = Price::EUR(500);                      // 1 x €5.00
$multiple = Price::USD(500, 4);                 // 4 x $5.00

Using these static calls, all monetary values are considered minor values (e.g. cents).

For a list of all available ISO 4217 currencies, take a look at Brick/Money's iso-currencies definition.

From parsed string values

Additionnaly, prices can also be parsed from "raw currency value" strings. This method can be useful but should always be used carefully since it may produce unexpected results in some edge-case situations, especially when "guessing" the currency :

use Whitecube\Price\Price;

$guessCurrency = Price::parse('5,5$');          // 1 x $5.50
$betterGuess = Price::parse('JMD 5.50');        // 1 x $5.50
$forceCurrency = Price::parse('10', 'EUR');     // 1 x €10.00

$multiple = Price::parse('6.008 EUR', null, 4); // 4 x €6.01
$force = Price::parse('-5 EUR', 'USD', 4);      // 4 x $-5.00

Parsing formatted strings is a tricky subject. More information on parsing string values below.

Accessing the Money objects (getters)

Once set, the base amount can be accessed using the base() method.

$perUnit = $price->base();                      // Brick\Money\Money
$allUnits = $price->base(false);                // Brick\Money\Money

Getting the currency instance is just as easy:

$currency = $price->currency();                 // Brick\Money\Currency

The total exclusive amount (with all modifiers except VAT):

$perUnit = $price->exclusive(true);             // Brick\Money\Money
$allUnits = $price->exclusive();                // Brick\Money\Money

The total inclusive amount (with all modifiers and VAT applied):

$perUnit = $price->inclusive(true);             // Brick\Money\Money
$allUnits = $price->inclusive();                // Brick\Money\Money

The VAT variables:

$vat = $price->vat();                           // Whitecube\Price\Vat
$percentage = $price->vat()->percentage();      // float
$perUnit = $price->vat()->money(true);          // Brick\Money\Money
$allUnits = $price->vat()->money();             // Brick\Money\Money

Comparing amounts

It is possible to check whether a price object's total inclusive amount is greater, lesser or equal to another value using the compareTo method:

$price = Price::USD(500, 2);                    // 2 x $5.00

$price->compareTo(999);                         // 1
$price->compareTo(1000);                        // 0
$price->compareTo(1001);                        // -1

$price->compareTo(Money::of(10, 'USD'));        // 0
$price->compareTo(Price::USD(250, 4));          // 0

For convenience there also is an equals() method:

$price->equals(999);                            // false
$price->equals(1000);                           // true
$price->equals(Money::of(10, 'USD'));           // true
$price->equals(Price::USD(250, 4));             // true

If you don't want to compare final modified values, there is a compareBaseTo method:

$price = Price::USD(500, 2);                    // 2 x $5.00

$price->compareBaseTo(499);                     // 1
$price->compareBaseTo(500);                     // 0
$price->compareBaseTo(501);                     // -1

$price->compareBaseTo(Money::of(5, 'USD'));     // 0
$price->compareBaseTo(Price::USD(500, 4));      // 0

Modifying the base price

The price object will forward all the Brick\Money\Money API method calls to its base value.

⚠️ Warning: In opposition to Money objects, Price objects are not immutable. Therefore, operations like plus, minus, etc. will directly modify the price's base value instead of returning a new instance.

use Whitecube\Price\Price;
use Brick\Money\Money;

$price = Price::ofMinor(500, 'USD')->setUnits(2);   // 2 x $5.00

$price->minus('2.00')                               // 2 x $3.00
    ->plus('1.50')                                  // 2 x $4.50
    ->dividedBy(2)                                  // 2 x $2.25
    ->multipliedBy(-3)                              // 2 x $-6.75
    ->abs();                                        // 2 x $6.75

Please refer to brick/money's documentation for the full list of available features.

💡 Nice to know: Whenever possible, you should prefer using modifiers to alter a price since its base value is meant to be constant. For more information on modifiers, please take at the "Adding modifiers" section below.

Setting units (quantities)

This package's default behavior is to consider its base price as the "per unit" price. When no units have been specified, it defaults to 1. Since "units" can be anything from a number of undividable products to a measurement, they are always converted to floats.

You can set the units amount (or "quantity" if you prefer) during instantiation:

use Whitecube\Price\Price;
use Brick\Money\Money;

$price = new Price(Money::ofMinor(500, 'EUR'), 2);      // 2 units of €5.00 each
$same = Price::EUR(500, 2);                             // same result
$again = Price::parse('5.00', 'EUR', 2);                // same result

...or modify it later using the setUnits() method:

$price->setUnits(1.75);                                 // 1.75 x €5.00

You can return the units count using the units() method (always float):

$quantity = $price->units();                            // 1.75

Setting VAT

VAT can be added by providing its relative value (eg. 21%):

use Whitecube\Price\Price;

$price = Price::USD(200);                   // 1 x $2.00

$price->setVat(21);                         // VAT is now 21.0%, or $0.42 per unit

$price->setVat(null);                       // VAT is unset

Once set, the price object will be able to provide various VAT-related information:

use Whitecube\Price\Price;

$price = Price::EUR(500, 3)->setVat(10);    // 3 x €5.00

$percentage = $price->vat()->percentage();  // 10.0

$perUnit = $price->vat()->money(true);      // €0.50
$allUnits = $price->vat()->money();         // €1.50

Setting modifiers

Modifiers are all the custom operations a business needs to apply on a price before displaying it on a bill. They range from discounts to taxes, including custom rules and coupons. These are the main reason this package exists.

Discounts

use Whitecube\Price\Price;
use Brick\Money\Money;

$price = Price::USD(800, 5)                         // 5 x $8.00
    ->addDiscount(-100)                             // 5 x $7.00
    ->addDiscount(Money::of(-5, 'USD'));            // 5 x $6.50

Taxes (other than VAT)

use Whitecube\Price\Price;
use Brick\Money\Money;

$price = Price::EUR(125, 10)                        // 10 x €1.25
    ->addTax(100)                                   // 10 x €2.25                     
    ->addTax(Money::of(0.5, 'EUR'));                // 10 x €2.75

Custom modifier types

Sometimes modifiers cannot be categorized into "discounts" or "taxes", in which case you can add your own modifier type:

use Whitecube\Price\Price;
use Brick\Money\Money;

$price = Price::USD(2000)                           // 1 x $20.00
    ->addModifier('coupon', -500)                   // 1 x $15.00                
    ->addModifier('extra', Money::of(2, 'USD'));    // 1 x $17.00

💡 Nice to know: Modifier types (tax, discount or your own) are useful for filtering, grouping and displaying sub-totals or price construction details. More information in the "Displaying modification details" section below.

Complex modifiers

Most of the time, modifiers are more complex to define than simple "+" or "-" operations. Depending on the level of complexity, there are a few options that will let you configure your modifiers just as you wish.

Closure modifiers

Instead of providing a monetary value to the modifiers, you can use a closure which will get a Whitecube\Price\Modifier instance. This object can then be used to perform some operations on the price value. Available operations are:

Method Description
add() Registers a plus() method call on the Money object.
subtract() Registers a minus() method call on the Money object.
multiply() Registers a multipliedBy() method call on the Money object.
divide() Registers a dividedBy() method call on the Money object.
abs() Registers a abs() method call on the Money object.

All these methods have the same signatures as their Brick\Money\Money equivalent. The reason we're not using the same method names is to imply object mutability.

use Whitecube\Price\Price;
use Whitecube\Price\Modifier;

$price = Price::USD(1250)
    ->addDiscount(function(Modifier $discount) {
        $discount->subtract(100)->multiply(0.95);
    })
    ->addTax(function(Modifier $tax) {
        $tax->add(250);
    })
    ->addModifier('lucky', function(Money $modifier) {
        $modifier->divide(2);
    });

Furthermore, using closure modifiers you can also add other useful configurations, such as:

Method Default Description
setKey(string) null Define an identifier on the modifier. This can be anything and its main purpose is to make a modifier recognizable on display, for instance a translation key or a CSS class name.
setPostVat(bool) false Indicate whether the modifier should be applied before (false) or after (true) the VAT has been calculated. More information on this feature below.
setPerUnit(bool) true Indicate whether the add() and subtract() operations define "per-unit" amounts instead of providing a fixed amount that would be applied no matter the quantity.
setAttributes(array) [] Define as many extra modifier attributes as needed. This can be very useful in order to display the applied modifiers in complex user interfaces.

Modifier classes

For even more flexibility and readability, it is also possible to extract all these features into their own class:

use Whitecube\Price\Price;

$price = Price::EUR(600, 5)
    ->addDiscount(Discounts\FirstOrder::class)
    ->addTax(Taxes\Gambling::class)
    ->addModifier('custom', SomeCustomModifier::class);

These classes have to implement the Whitecube\Price\PriceAmendable interface, which then looks more or less like this:

type; } /** * Define the modifier type (tax, discount, other, ...) * * @param null|string $type * @return $this */ public function setType($type = null) { $this->type = $type; return $this; } /** * Return the modifier's identification key * * @return null|string */ public function key() : ?string { return 'very-random-tax'; } /** * Get the modifier attributes that should be saved in the * price modification history. * * @return null|array */ public function attributes() : ?array { return [ 'subtitle' => 'Just because we don\'t like you today', 'color' => 'red', ]; } /** * Whether the modifier should be applied before the * VAT value has been computed. * * @return bool */ public function appliesAfterVat() : bool { return false; } /** * Apply the modifier on the given Money instance * * @param \Brick\Money\Money $build * @param float $units * @param bool $perUnit * @param null|\Brick\Money\Money $exclusive * @param null|\Whitecube\Price\Vat $vat * @return null|\Brick\Money\Money */ public function apply(Money $build, $units, $perUnit, Money $exclusive = null, Vat $vat = null) : ?Money { if(date('j') > 1) { // Do not apply if it's not the first day of the month return null; } // Otherwise add $2.00 per unit $supplement = Money::of(2, 'EUR'); return $build->plus($perUnit ? $supplement : $supplement->multipliedBy($units, RoundingMode::HALF_UP)); } } ">
use Brick\Money\Money;
use Brick\Math\RoundingMode;
use Whitecube\Price\Modifier;
use Whitecube\Price\PriceAmendable;

class SomeRandomModifier implements PriceAmendable
{
    /**
     * The current modifier "type"
     *
     * @return string
     */
    protected $type;

    /**
     * Return the modifier type (tax, discount, other, ...)
     *
     * @return string
     */
    public function type() : string
    {
        return $this->type;
    }

    /**
     * Define the modifier type (tax, discount, other, ...)
     *
     * @param null|string $type
     * @return $this
     */
    public function setType($type = null)
    {
        $this->type = $type;

        return $this;
    }

    /**
     * Return the modifier's identification key
     *
     * @return null|string
     */
    public function key() : ?string
    {
        return 'very-random-tax';
    }

    /**
     * Get the modifier attributes that should be saved in the
     * price modification history.
     *
     * @return null|array
     */
    public function attributes() : ?array
    {
        return [
            'subtitle' => 'Just because we don\'t like you today',
            'color' => 'red',
        ];
    }

    /**
     * Whether the modifier should be applied before the
     * VAT value has been computed.
     *
     * @return bool
     */
    public function appliesAfterVat() : bool
    {
        return false;
    }

    /**
     * Apply the modifier on the given Money instance
     *
     * @param \Brick\Money\Money $build
     * @param float $units
     * @param bool $perUnit
     * @param null|\Brick\Money\Money $exclusive
     * @param null|\Whitecube\Price\Vat $vat
     * @return null|\Brick\Money\Money
     */
    public function apply(Money $build, $units, $perUnit, Money $exclusive = null, Vat $vat = null) : ?Money
    {
        if(date('j') > 1) {
            // Do not apply if it's not the first day of the month
            return null;
        }

        // Otherwise add $2.00 per unit
        $supplement = Money::of(2, 'EUR');
        return $build->plus($perUnit ? $supplement : $supplement->multipliedBy($units, RoundingMode::HALF_UP));
    }
}

If needed, it is also possible to pass arguments to these custom classes from the Price configuration:

use Brick\Money\Money;
use Whitecube\Price\Price;

$price = Price::EUR(600, 5)
    ->addModifier('lucky-or-not', BetweenModifier::class, Money::ofMinor(-100, 'EUR'), Money::ofMinor(100, 'EUR'));
use Brick\Money\Money;
use Whitecube\Price\PriceAmendable;

class BetweenModifier implements PriceAmendable
{
    protected $minimum;
    protected $maximum;

    public function __construct(Money $minimum, Money $maximum)
    {
        $this->minimum = $minimum;
        $this->maximum = $maximum;
    }

    // ...
}

Before or after VAT?

Depending on the modifier's nature, VAT could be applied before or after its intervention on the final price. All modifiers can be configured to be executed during one of these phases.

By default modifiers are added before VAT is applied, meaning they will most probably also modify the VAT value. In order to prevent that, it is possible to add a modifier on top of the calculated VAT. Legally speaking this is honestly quite rare but why not:

use Whitecube\Price\Price;

$price = Price::USD(800, 5)->addTax(function($tax) {
    $tax->add(200)->setPostVat();
});

In custom classes, this is handled by the appliesAfterVat method.

⚠️ Warning: Applying modifiers after VAT will alter the modifiers execution order. Prices will first apply all the modifiers that should be executed before VAT (in order of appearance), then the VAT itself, followed by the remaining modifiers (also in order of appearance).

Inclusive prices will contain all the modifiers (before and after VAT), but exclusive prices only contain the "before VAT" modifiers by default. If you consider the "after VAT" modifiers to be part of the exclusive price, you can always count them in by providing $includeAfterVat = true as second argument of the exclusive() method:

use Whitecube\Price\Price;

$price = Price::USD(800, 5)->setVat(10)->addTax(function($tax) {
    $tax->add(200)->setPostVat();
});

$price->exclusive();                // $40.00
$price->exclusive(false, true);     // $50.00
$price->inclusive();                // $54.00

Displaying modification details

When debugging or building complex user interfaces, it is often necessary to retrieve the complete Price modification history. This can be done using the modifications() method after all the modifiers have been added on the Price instance:

$history = $price->modifications(); // Array containing chronological modifier results

Each history item contains the amount it applied to the total price. If you want to query these modifications with their "per-unit" value:

use Whitecube\Price\Modifier;

$perUnitHistory = $price->modifications(true);

Filter this history based on the modifier types:

use Whitecube\Price\Modifier;

$history = $price->modifications(false, Modifier::TYPE_DISCOUNT);  // Only returning discount results

Most of the time you won't need all the data from the modifications() method, only the modification totals. These can be returned using the discounts(), taxes() and the generic modifiers() methods:

use Whitecube\Price\Modifier;

$totalDiscounts = $price->discounts();
$totalDiscountsPerUnit = $price->discounts(true);

$totalTaxes = $price->taxes();
$totalTaxesPerUnit = $price->taxes(true);

$totalAllModifiers = $price->modifiers();
$totalAllModifiersPerUnit = $price->modifiers(true);

$totalCustomTypeModifiers = $price->modifiers(false, 'custom');
$totalCustomTypeModifiersPerUnit = $price->modifiers(true, 'custom');

Output

By default, all handled monetary values are wrapped into a Brick\Money\Money object. This should be the only way to manipulate these values in order to avoid decimal approximation errors.

JSON

Prices can be serialized to JSON and rehydrated using the Price::json($value) method, which can be useful when storing/retrieving prices from a database or an external API for example:

use Whitecube\Price\Price;

$json = json_encode(Price::USD(999, 4)->setVat(6));

$price = Price::json($json);    // 4 x $9.99 with 6% VAT each

💡 Nice to know: you can also use Price::json() in order to create a Price object from an associative array, as long as it contains the base, currency, units and vat keys.

Parsing values

There are a few available methods that will allow to transform a monetary string value into a Price object. The generic parseCurrency method will try to guess the currency type from the given string:

use Whitecube\Price\Price;

$fromIsoCode = Price::parse('USD 5.50');        // 1 x $5.50
$fromSymbol = Price::parse('10€');              // 1 x €10.00

For this to work, the string should always contain an indication on the currency being used (either a valid ISO code or symbol). When using symbols, be aware that some of them ($ for instance) are used in multiple currencies, resulting in ambiguous results.

When you're sure which ISO Currency is concerned, you should directly pass it as the second parameter of the parse() method:

use Whitecube\Price\Price;

$priceEUR = Price::parse('5,5 $', 'EUR');       // 1 x €5.50
$priceUSD = Price::parse('0.103', 'USD');       // 1 x $0.10

When using dedicated currency parsers, all units/symbols and non-numerical characters are ignored.


🔥 Sponsorships

If you are reliant on this package in your production applications, consider sponsoring us! It is the best way to help us keep doing what we love to do: making great open source software.

Contributing

Feel free to suggest changes, ask for new features or fix bugs yourself. We're sure there are still a lot of improvements that could be made, and we would be very happy to merge useful pull requests.

Thanks!

Made with ❤️ for open source

At Whitecube we use a lot of open source software as part of our daily work. So when we have an opportunity to give something back, we're super excited!

We hope you will enjoy this small contribution from us and would love to hear from you if you find it useful in your projects. Follow us on Twitter for more updates!

You might also like...
Database management in a single PHP file

Adminer - Database management in a single PHP file Adminer Editor - Data manipulation for end-users https://www.adminer.org/ Supports: MySQL, MariaDB

:panda_face: Jitamin is a free software written in PHP, intended to handle the project management over the web. QQ群: 656868

Jitamin Jitamin (pronounced /ˈdʒɪtəmɪn/) is a free software written in PHP, intended to handle the project management over the web. Jitamin is inspire

Open Source Voucher Management System is a web application for manage voucher. used PHP with Laravel Framework and use MySQL for Database.
Open Source Voucher Management System is a web application for manage voucher. used PHP with Laravel Framework and use MySQL for Database.

Voucher Management System is a web application for manage voucher. You can create and manage your voucher. Voucher Management System is used PHP with Laravel Framework and use MySQL for Database.

Hotel Management System using MySQL, Php, Ajax, Jquery and HTML
Hotel Management System using MySQL, Php, Ajax, Jquery and HTML

Hotel-Management-System-Ajax-PHP-Mysql A hotel management system in which clients can perform operations such as booking a room and event. It is possi

School/College management system in PHP

School-Management-System This is a system with all necessary features a school/college needes in their this digital era such as student,teacher,princi

This is an implementation of football club management. HTML,CSS,PHP

This is an implementation of football club management. HTML,CSS,PHP were used in the construction of this project. Note that database is not included into the code, but the class name and attributes can be found within the code section. Construction and system design can be found in - https://github.com/Mubin42/System-Design-of-Football-Club-Management

Customer Relationship Management (CRM) portal using PHP Codeigniter 4 & Tailwind CSS framework.
Customer Relationship Management (CRM) portal using PHP Codeigniter 4 & Tailwind CSS framework.

CRM Portal Customer Relationship Management (CRM) portal using PHP Codeigniter 4 & Tailwind CSS framework. Screenshots User (Dashboard) Admin (Employe

ZAP CRM is Customer Relationship Management portal built using PHP Codeigniter 4 & Tailwind CSS framework.
ZAP CRM is Customer Relationship Management portal built using PHP Codeigniter 4 & Tailwind CSS framework.

ZAP CRM ZAP CRM is Customer Relationship Management portal built using PHP Codeigniter 4 & Tailwind CSS framework. Screenshots User (Dashboard) Admin

UserFrosting is a secure, modern user management system written in PHP and built on top of the Slim Microframework, Twig templating engine, and Eloquent ORM.
UserFrosting is a secure, modern user management system written in PHP and built on top of the Slim Microframework, Twig templating engine, and Eloquent ORM.

UserFrosting 4.6 Branch Version Build Coverage Style master hotfix develop https://www.userfrosting.com If you simply want to show that you like this

Comments
  • MoneyMismatchException:contextMismatch when using different context

    MoneyMismatchException:contextMismatch when using different context

    When using this library with a Money instance with a custom context calculating the inclusive/exclusive price will throw an exception.

    The monies do not share the same context. If this is intended, use plus($money->toRational()) instead of plus($money).

    In my use case the context should not round the numbers which could be achieved with a custom context. The default context auto rounds the values to the default rounding of the used currency.

    opened by BertKooij 1
  • Add PHP 8.1 compatibility & Fix minimum PHP version to 7.4

    Add PHP 8.1 compatibility & Fix minimum PHP version to 7.4

    I am not sure if this should be part of a new major release or if a minor would suffice.

    I think a minor version would work, seeing as the addition of the 7.4 requirement would mean anyone on a lower version of PHP just won't get upgraded automatically.

    I suggest we at least attempt to keep 7.4 compatibility until November 28, 2022, the official end of support for that PHP version. Unless we really really need 8.0 features, but it seems a bit unlikely.

    Any thoughts?

    opened by voidgraphics 0
  • fix(parser): Remove PHP warnings on unknown modifier '\'

    fix(parser): Remove PHP warnings on unknown modifier '\'

    They say that A picture is worth a thousand words...

    image

    This WARNING is thrown while parsing Price objects from strings. This is due to the regex pattern generator not knowing that the forward slash (/) character should be escaped.

    More specifically, this warning is raised when the following currency symbols are being tested in the regex: | Currency Code | Symbol | Generated Pattern (Error Highlighted) | | -------------------- | ---------- | ------- | | PAB | B/. | image | | PEN | S/. | image |

    In order to fix this, we only need to flag the forward character (/) as part of the escaped regex characters, which is what this little PR does.

    opened by iksaku 0
Releases(v2.2.0)
  • v2.2.0(Jan 17, 2022)

    New features:

    • PHP 8.1 compatibility
    • toMinor method to easily access minor amount

    Bug fixes:

    • Fixed parsing of values with narrow non-breaking spaces (a73bb01e96b1e85cefc67edb3bf7d49ce5be8ee5)
    Source code(tar.gz)
    Source code(zip)
  • v2.1.1(Aug 14, 2021)

    New feature update :

    • Price::formatUsing() : Now accepts callable closures, custom formatter class names (string) and instances (as long as they extend \Whitecube\Price\Formatting\CustomFormatter). Examples in the docs and tests.
    Source code(tar.gz)
    Source code(zip)
  • v2.1.0(Aug 13, 2021)

    New features:

    • Price::format(Price|Vat|Money $value, string $locale) : formats given monetary value into a human readable string respecting the target locale's formatting syntax.
    • Price::formatUsing(callable $closure) : add your own formatting functions!
    Source code(tar.gz)
    Source code(zip)
  • v2.0.2(Aug 11, 2021)

    Bug fixes :

    • Fixed PHP warning when parsing price strings due to currency symbols containing unescaped special characters in regex pattern - #7. Thanks @iksaku.
    Source code(tar.gz)
    Source code(zip)
  • v2.0.1(Mar 4, 2021)

  • v2.0.0(Feb 12, 2021)

  • v1.2.0(Jul 29, 2020)

    New features:

    • $price->amount() and $price->exclusiveAmount() will return the exclusive money amount (including modifiers) as an integer string ;
    • $price->inclusiveAmount() will return the inclusive money amount (including modifiers) as an integer string ;
    • $price->baseAmount() will return the base (original, without modifiers) money amount as an integer string ;
    • $price->currency() will return the underlying Money\Currency instance.

    Bug fixs/Enhancements:

    • Currency extraction from complex parsable currency strings has been optimized
    • Currency recognition regexes have been fixed for some exotic currency unit symbols
    Source code(tar.gz)
    Source code(zip)
Owner
Whitecube
Digital Agency based in Belgium
Whitecube
Centreon is a network, system and application monitoring tool. Centreon is the only AIOps Platform Providing Holistic Visibility to Complex IT Workflows from Cloud to Edge.

Centreon - IT and Application monitoring software Introduction Centreon is one of the most flexible and powerful monitoring softwares on the market;

Centreon 14 Dec 16, 2022
Laravel-Library-Management-system is nice to management library system...

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

Eng Hasan Hajjar 2 Sep 30, 2022
DooTask is a lightweight open source online project task management tool that provides various document collaboration tools, online mind mapping, online flowcharting, project management, task distribution, instant IM, file management and other tools.

DooTask is a lightweight open source online project task management tool that provides various document collaboration tools, online mind mapping, online flowcharting, project management, task distribution, instant IM, file management and other tools.

kuaifan 3k Jan 5, 2023
mini Project in Laravel and vue js. Real World Laravel 8x + vue js Dashboard.Task management and project management system

mini Project in Laravel and vue js. Real World Laravel 8x + vue js Dashboard.Task management and project management system. Dashboard features such as: Complete Dashboard, Custom Authentication, Email Verification, custom-login-register-forgot password (without jetstream).

Hasmukh Dharajiya 2 Sep 20, 2022
An automated library management system developed in Laravel 4.2 PHP MVC Framework

An automated system to manage a public library. Admin panel for librarians to control and manage the system easily through an interactive interface.

Prabhakar Gupta 244 Dec 27, 2022
A simple wrapper for PHP Intervention Library to provide a more simple interface and convenient way to convert images to webp

This package is a simple wrapper for PHP Intervention Library to provide a more simple interface and convenient way to convert images to webp - next generation format - extension, and resize them to render only needed sizes.

eyad hamza 18 Jun 28, 2022
Library management system

Scriptorium management system Amicus Plato, sed magis amica veritas In the copying process, there was typically a division of labor among the monks wh

Roman Movchan 4 Jan 9, 2022
Library management system with Laravel.

Laravel Library Management System Quick Start clone the repo cd Laravel-libraray-management-system composer install cp or copy .env.example .env php a

Tauseed 16 Dec 28, 2022
Simple Dynamic DNS Web management self-hosting. Run over dnsmasq.

MyDDNS [BETA] Simple Dynamic DNS Web management self-hosting. It use dnsmasq. It was inspired on duckdns.org. Preparation You need root access to a se

Iván Eixarch 4 Jul 6, 2022
Library JGU is a website created for a university library system information. Made with PHP & TailwindCSS.

Library JGU Library JGU is a website created for a university library system information. Made with PHP & TailwindCSS. Key Features • How To Use • Rel

Azkazikna Ageung Laksana 23 Oct 7, 2022