Overview
The Table Rate Shipping add-on provides a flexible, zone-based shipping system for Lunar. It integrates with the core shipping modifier pipeline, allowing storefronts to offer multiple shipping methods with pricing that varies by zone, cart total, weight, or other criteria. Key concepts:- Shipping Zones define geographic regions (unrestricted, by country, state, or postcode).
- Shipping Methods represent the types of delivery available (e.g., standard, express, collection).
- Shipping Rates link a method to a zone with tiered pricing.
- Shipping Exclusion Lists prevent specific products from being shipped to certain zones.
Installation
Install via Composer:Configuration
The configuration file is published atconfig/lunar/shipping-tables.php.
Permissions
The add-on registers ashipping:manage permission and enforces it on the Shipping Methods, Shipping Zones, and Shipping Exclusion Lists resources in the admin panel. Staff members need this permission (either directly or via a role) to view or manage shipping configuration.
The permission is created automatically by a migration when the add-on is installed. See Access Control for guidance on assigning permissions to roles and staff.
Models
ShippingZone
Relationships
ShippingMethod
Relationships
ShippingRate
Lunar\Models\Contracts\Purchasable interface and uses the HasPrices trait, meaning prices are stored in Lunar’s core prices table with support for tiered pricing and multiple currencies.
Relationships
ShippingZonePostcode
Relationships
ShippingExclusionList
Relationships
ShippingExclusion
Relationships
Method Availability
Each shipping method exposes two ways to control when it can be offered to customers: an availability schedule and an optional weight range.Availability Schedule
Shipping methods use an availability schedule to define when the method can be selected. The schedule replaces the older single daily cutoff time and supports finer-grained rules (for example, different cutoffs per day of the week, or unavailable on specific dates). The schedule is managed through the Shipping Method page in the admin panel. When the cart is evaluated, the shipping rate resolver checks the schedule for each method and only returns rates from methods that are currently available.Weight Constraints
min_weight and max_weight on the shipping method allow restricting the method to carts within a given weight range. Both fields are optional; leaving them empty means no lower or upper bound is applied. weight_unit defines the unit used by both values.
The total cart weight is calculated from each cart line’s purchasable weight multiplied by its quantity. Methods whose constraints are not satisfied are excluded from the resolver’s results.
Drivers
Each shipping method uses a driver to determine how pricing is resolved. The add-on ships with four built-in drivers.Ship By
Driver identifier:ship-by
The most flexible driver. Pricing is based on either the cart total or the total weight of items in the cart. Prices are stored as tiered rates on the shipping rate, where each tier’s min_quantity represents the threshold (cart subtotal in minor units, or total weight).
Data configuration:
Flat Rate
Driver identifier:flat-rate
Charges a flat rate per order, with optional tiered pricing based on the cart subtotal. Prices are stored on the shipping rate using Lunar’s pricing system with quantity tiers representing cart subtotal thresholds.
Free Shipping
Driver identifier:free-shipping
Offers free shipping when the cart meets a minimum spend requirement.
Data configuration:
Collection
Driver identifier:collection
Allows customers to collect their order in store. Returns a shipping option with a price of zero and sets collect: true on the shipping option, which can be used to identify collection orders in the storefront.
Per-Currency Pricing
Shipping rates store their base price per currency, not just for the store’s default currency. Each currency enabled on the store can be assigned its own base price through the Shipping Rates page in the admin panel. Tiered pricing (used byship-by and flat-rate) continues to be defined alongside, using Lunar’s core pricing system.
Shipping Discounts
The add-on registers aShippingDiscount discount type that targets the shipping portion of the cart. It is configured through the Discounts area of the admin panel.
shipping_method_id) or act as a catch-all (no method selected), and offers one of two adjustments:
- Percentage — reduces the matched shipping option price by a percentage.
- Fixed per currency — replaces the matched shipping option price with a fixed value per currency code. A value of
0produces free shipping.
Storefront Usage
This add-on registers aShippingModifier with Lunar’s shipping modifier pipeline. Shipping options are automatically resolved and available through the ShippingManifest:
ShippingOption instances that are added to the manifest.
If an existing storefront already uses the
ShippingManifest to retrieve shipping options, no changes are needed. The add-on integrates automatically.Advanced Usage
Retrieving Supported Drivers
Resolving a Driver Directly
Resolving Shipping Zones
The zone resolver finds matching zones based on address criteria. Each method is optional; combining them makes the lookup more specific.unrestricted, plus any zones matching the specified country, state, or postcode criteria.
Resolving Shipping Rates
The rate resolver finds applicable shipping rates for a cart, filtering by customer group, cutoff time, and stock availability.Resolving Shipping Options
The option resolver takes shipping rates and resolves them into pricedShippingOption instances using each rate’s driver.
Postcode Resolvers Added in 1.5
Postcode formats vary considerably between countries, so the add-on splits a raw postcode into a set of “parts” that are matched againstShippingZonePostcode records. The default Lunar\Shipping\Resolvers\PostcodeResolver works well for UK-style postcodes (and any country that follows a similar prefix structure), but custom resolvers can be registered for stores operating in regions where a different breakdown is needed.
The PostcodeResolverInterface
A resolver implementsLunar\Shipping\Interfaces\PostcodeResolverInterface:
supportsCountrydeclares which countries the resolver handles. Returningtruefor every country makes the resolver a catch-all.getPartsreturns the postcode permutations to match against the zone’s stored postcodes. Wildcards (*) are honored by the zone resolver.
Registering a custom resolver
Resolvers are registered through theLunar\Shipping\Facades\Postcode facade, typically in the boot method of a service provider:
Example resolver
If no registered resolver supports the cart’s country, a
Lunar\Shipping\Exceptions\NoPostcodeResolverException is thrown. The default resolver ships unrestricted, so this only applies when it has been removed.Events
ShippingOptionResolvedEvent
Order Observer
When an order is created or updated, the add-on automatically resolves the shipping zone from the order’s shipping address and attaches it to the order via theorder_shipping_zone pivot table. The zone name is also stored in the order’s meta for search indexing.