Overview
Products represent the items available for sale in a store. Every product belongs to aProductType, which determines which attributes are available to it and its variants, and can optionally belong to a Brand.
A product always has at least one variant. When a product has only a single variant, the editing experience appears as though the product itself is being edited directly, but behind the scenes the purchasable data (pricing, stock, tax, dimensions) lives on the variant.
Fields
Products do not use soft deletes. A product with order history cannot be hard-deleted;
$product->hasOrderHistory() reports whether any of its variants appear on a historical order line, and such products should be archived instead of deleted.Relationships
Scopes
Creating a Product
Name and description
Unlike custom attributes,name, description, and short_description are dedicated, translatable columns on the product, guaranteeing every product has a real, queryable name. They are stored as a locale-keyed map and read through the translate() helper:
attribute_data remains available for genuinely custom, per-product-type attributes. See the Attributes reference for details.
Filtering by status
Channels
Products support multi-channel availability through theHasChannels trait. When a product is created, all channels are automatically synced. Each channel can be independently enabled or disabled, with optional start and end dates for scheduled availability.
Scheduling a channel
Filtering by channel
Customer Groups
Products can be assigned to customer groups with optional scheduling. This controls whether the product is visible and purchasable for members of each group.Scheduling a customer group
Filtering by customer group
ThecustomerGroup scope accepts a single customer group (or ID), or a collection/array of customer groups or IDs.
Product Types
Product types categorize products and determine which attributes are available during editing (e.g. Television, T-Shirt, Book, Phone).Fields
A product type cannot be deleted while products still reference it — reassign or remove them first, otherwise
ProductTypeActionException is thrown.Relationships
Scopes
Creating a product type
Screen Type associated to a TVs product type would make that field available on any product with that type.
Attributes can be associated using a standard polymorphic relationship:
Product and ProductVariant attributes can be associated to a product type, and each will display on the corresponding model when editing.
Retrieving the product type relationship
Product Options
Product options define the different variations available for a product. EachProductOption has a set of ProductOptionValue models. For example, a ProductOption called “Color” could have values like “Blue”, “Red”, and “Green”.
Fields
Relationships
Scopes
Creating a ProductOption
ProductOptionValue Fields
Product Option Meta
BothProductOption and ProductOptionValue models include a meta field for storing custom information such as color hex values, image links, or other display data.
Lunar makes no assumptions about the structure of the meta JSON field. Any values can be stored in whatever format the application requires.
Product Associations
Products can be associated with other products as cross-sells, up-sells, or alternates. See the Associations reference for full details on creating and managing product associations.Variants
Variants represent the different purchasable permutations of a product, such as “Small Blue T-shirt” or “Size 9 Leather Boots”. The product acts as the parent, and variants hold the specific data including pricing, inventory, shipping information, and product identifiers. A product always has at least one variant.Fields
Stock is a cached rollup derived from the variant’s per-location stock levels and an append-only movement ledger. See the Inventory reference for the full stock model, location tracking, and movement API.
Relationships
Scopes
Selling Policy
selling_policy decides whether a variant can be sold relative to its stock, cast to the Lunar\Core\Enums\SellingPolicy enum:
Product Identifiers
Each variant can store product identifiers for use in internal systems or external services. SKU (Stock Keeping Unit) — A code (usually eight alphanumeric digits) used to track stock levels internally. Each variant of a product typically has a unique SKU. GTIN (Global Trade Item Number) — An internationally recognized product identifier, often accompanying a barcode. Useful with services like Google Shopping to help classify products. MPN (Manufacturer Part Number) — An identifier from the manufacturer that differentiates a product among similar items from the same brand. EAN (European Article Number) — A series of characters that identifies specific products within an inventory system.Creating Variants
A product variant requires a product and a tax class.Shipping
By default, all product variants are marked as shippable. To mark a variant as non-shippable:Dimensions
Products can store dimension data on each variant. The available dimensions are:- Length
- Width
- Height
- Weight
- Volume
_value and _unit column in the database:
Configuring measurements
Available units of measure can be configured in thelunar/shipping.php config file. The defaults include:
Length: m, mm, cm, ft, in
Weight: kg, g, lbs
Volume: l, ml, gal, floz
Getting and converting measurement values
The raw*_value and *_unit values can be accessed directly, but Lunar also provides an accessor for each dimension that supports conversion:
Volume calculation
Volume can be calculated automatically from the length, width, and height dimensions, or set manually:Pricing
Pricing is defined at the variant level: each variant has its own price for each currency, plus optional customer group pricing and quantity breaks. See the Pricing reference for the full API, including thePricingManager facade used to fetch the correct price for a customer.
To retrieve all prices across a product’s variants without loading the variants individually, use the prices relationship on the product:
Full Example
This example walks through creating a pair of Dr. Martens boots with multiple size and color variants. The steps involved are:- Create the product type
- Create the initial product
- Create product options and their values
- Create the variants
Set up the product type
Create the initial product
Create product options
Based on the example above, two options are needed: Size and Color.Create product option values
Create the variants
With the options and values defined, variants can be created for each combination. Each variant needs a product, tax class, SKU, and at least one price.
SKUs, pricing, and other variant details can be adjusted as needed before publishing.