Skip to main content
Lunar provides currency-aware price formatting and display for storefront use.

Overview

When displaying prices on a storefront, it is important to show the correct format relative to the currency the customer is purchasing in. Every storefront is different. Lunar provides a default price formatter that suits most use cases, while also making it straightforward to swap in a custom implementation for stores with specific formatting requirements.

The Price model

Both the price and compare_price fields are automatically cast to Lunar\DataTypes\Price objects when accessed.

Relationships

Tax helper methods

The Lunar\Models\Price model provides methods for retrieving prices with or without tax applied, based on the lunar.pricing.stored_inclusive_of_tax configuration value.

Overriding the tax zone Added in 1.5

Each method accepts an optional Lunar\Models\TaxZone to override the zone used when computing the tax rate. When no zone is passed, the store’s default tax zone is used.
This is useful when displaying product prices for a known visitor region before the cart is built. Once items are in the cart, the cart’s own tax_zone_id (see Setting the Tax Zone) drives tax-inclusive line totals.

The Price data type

The Lunar\DataTypes\Price class is used throughout Lunar whenever a price value needs formatting. It is not limited to the Lunar\Models\Price model. The following models also have attributes that return Lunar\DataTypes\Price instances:

Lunar\Models\Order

  • sub_total
  • discount_total
  • shipping_total
  • tax_total
  • total

Lunar\Models\OrderLine

  • unit_price
  • sub_total
  • discount_total
  • tax_total
  • total

Lunar\Models\Transaction

  • amount

Price formatting

The class responsible for price formatting is configured in the config/lunar/pricing.php file:

DefaultPriceFormatter

The Lunar\Pricing\DefaultPriceFormatter ships with Lunar and handles most use cases for formatting a price. To demonstrate, start by creating a standard price model:

Raw value

Return the raw integer value as stored in the database:

Decimal value

Return the decimal representation of the price. The decimal value accounts for the number of decimal places configured on the currency. For example, if the currency has 2 decimal places:
These two values are identical in this example. The unitDecimal method factors in the unit_quantity of the purchasable model. Consider the following:
By setting unit_quantity to 10, Lunar is told that 10 individual units make up this product at this price point. This is useful for items where a single unit would cost less than the smallest currency denomination (e.g. 0.001 EUR).
Now the difference becomes clear:
The unitDecimal method divides by the unit quantity, giving the per-unit cost of 0.01.

Formatted currency string

The formatted price uses the native PHP NumberFormatter. A locale and formatting style can be specified:

Full method reference

Creating a custom formatter

A custom formatter must implement Lunar\Pricing\PriceFormatterInterface and accept $value, $currency, and $unitQty as constructor parameters.
The methods can accept any number of arguments beyond those defined in the interface. The formatter is not bound to the same parameter signatures as DefaultPriceFormatter. Once implemented, register the custom formatter in config/lunar/pricing.php:

Model casting

For custom models that need price formatting, Lunar provides a cast class. The only requirement is that the column stores an integer value.
The Lunar\Base\Casts\Price cast resolves the currency from the model’s currency relationship. If no currency relationship exists, it falls back to the default currency.