Appearance
Product Variations & Lines
Flow ID: CF-25 | Module(s): variations, Product domain | Complexity: High
Business Overview
Variations model product options (Size, Color) as a matrix. Products with the same variations are grouped for frontend switching.
Hierarchy:
- Variation Group: Dimension (e.g., "Size") with display type (text, hex-color, image, range)
- Variation Value: Option (e.g., "S", "M", "L")
- Product Code (SKU): Purchasable unit with independent stock
- Product Variation: Links product to group, designates master
Key business behaviors:
- Stock is per-SKU (
product_codes.stock) - Cart stores
productCodeId(specific SKU) - Master product in variation group is the "primary" display product
- Display position: 0=ALL, 1=PRODUCT only, 2=FILTER only, 3=NONE
API Reference
REST Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /rest/product/variation | Guest | List product variations |
| GET | /rest/product/variation-group | Guest | List variation groups (sorts: priority) |
| GET | /rest/product/variation-value | Guest | List variation values |
| GET | /rest/product/line | Guest | List product codes/SKUs |
Full CRUD with Backend auth for all.
Domain Layer
| Component | Path |
|---|---|
| Variation Service | src/Domains/Product/Variation/Service.php |
| VariationGroup Service | src/Domains/Product/Variation/Group/Service.php |
| VariationValue Service | src/Domains/Product/Variation/Value/Service.php |
| Line Service | src/Domains/Product/Line/Service.php |
Note: product_code_attributes table maps SKU → variation values (not product_variation_values).
Client Extension Points
- Stock aggregation: Override Service for custom stock summing
- Master selection: WriteService logic for
is_masterdesignation - Filter config:
category_level_for_variations_in_sidebar,enableProductVariations - Attribute groups: Registry
AFFILIATION_ATTRS_GROUPS.GROUPS_FOR_SIZE/COLOR
Data Model
variation_groups
| Column | Type | Description |
|---|---|---|
id | int (PK, AI) | Group identifier |
display_type | varchar | Rendering mode: text, hex-color, image, range |
priority | int | Sort order for display |
variation_groups_mui
| Column | Type | Description |
|---|---|---|
id | int (PK, AI) | Translation row ID |
variation_group_id | int (FK) | Parent group |
name | varchar | Display name (e.g., "Size", "Color") |
lang | varchar | Language code |
variation_values / variation_values_mui
| Column | Type | Description |
|---|---|---|
id | int (PK, AI) | Value identifier |
variation_group_id | int (FK) | Parent group |
hex_value | varchar (nullable) | Hex color code (for hex-color type) |
image | varchar (nullable) | Image path (for image type) |
product_variations
| Column | Type | Description |
|---|---|---|
id | int (PK, AI) | Row ID |
product_id | int (FK) | Product in the variation group |
variation_group_id | int (FK) | Variation dimension |
is_master | tinyint | 1 = primary display product |
priority | int | Sort position |
product_codes (SKUs)
| Column | Type | Description |
|---|---|---|
id | int (PK, AI) | SKU identifier |
product_id | int (FK) | Parent product |
stock | int | Available stock for this SKU |
sku | varchar | External SKU code |
barcode | varchar (nullable) | EAN/barcode |
product_code_attributes
| Column | Type | Description |
|---|---|---|
id | int (PK, AI) | Row ID |
product_code_id | int (FK) | SKU |
variation_value_id | int (FK) | Attribute value (e.g., "Red", "XL") |
Variation Traits (Legacy Controllers)
Two shared traits encapsulate the variation logic used across storefront and admin controllers:
ProductVariationsTrait
- Merges live product data with variation definitions
- Builds variation group data structures including SEO-friendly URLs for each variant
- Used when rendering the product detail page variation matrix
ProductVariationsListingTrait
- Filters variation products from listing queries (excludes child/non-master products per configuration)
- Loads variation groups for displayed products
- Processes variation filter parameters from the query string (e.g.,
?variation_1=3&variation_2=7)
Trait Usage
| Controller | Trait(s) | Context |
|---|---|---|
Adv_products_admin.php | ProductVariationsTrait | Admin product editing |
AdvApiVariationsController.php | ProductVariationsTrait | Admin API for variation management |
Adv_products.php | ProductVariationsTrait, ProductVariationsListingTrait | Storefront product detail + listings |
| Listing controllers | ProductVariationsListingTrait | Category/search result pages |
Legacy AJAX API
These endpoints are served by AdvApiVariationsController (ecommercen/api/controllers/AdvApiVariationsController.php) and are used by the admin panel Vue components to manage variation groups, values, and product assignments. All endpoints accept JSON request bodies (parsed via jsonDecodeInputStream()) and return JSON responses via sendOutput().
Base path: /api/variations/{method} (routed via api/api_variations)
| Method | Path | Parameters | Response | Description |
|---|---|---|---|---|
| POST | /api/variations/getVariationGroupProductsApi | productId (int, required) | {variationGroupProducts: [...]} | Get all products in the same variation group as the given product |
| POST | /api/variations/updateProductVariation | productId (int, required), productVariation[] (array, required), masterProductId (int, optional) | {} | Update variation value assignments for a product; returns 422 if any values are empty |
| POST | /api/variations/updateVariationGroupMaster | groupId (int, required), productId (int, required) | {} | Set a product as the master (primary display) in a variation group |
| POST | /api/variations/getAllVariation | (none) | {allVariation: [...]} | Get all variation values across all groups |
| POST | /api/variations/getVariationGroupMui | groupId (int, required) | {variationGroupMui: [...]} | Get multi-language names for a variation group |
| POST | /api/variations/getVariationGroupName | productId (int, required) | {variationGroupName: ...} | Get the variation group name for a product |
| POST | /api/variations/getVariationGroupId | productId (int, required) | {variationGroupId: ...} | Get the variation group ID that a product belongs to |
| POST | /api/variations/getProductVariations | variationGroupProductIds[] (array, required) | {productVariationData: {[productId]: {[groupId]: {...}}}} | Get variation details for multiple products, keyed by product ID and group ID |
| POST | /api/variations/deleteProductFromVariationGroup | groupId (int, required), productId (int, required) | {} | Remove a product from a variation group |
| POST | /api/variations/addVariationProductToGroup | groupId (int, required), productId (int, required) | {} | Add a product to an existing variation group; returns 422 if product is already in another group |
| POST | /api/variations/addVariationProductToGroup (new group) | groupId (falsy/0), productId (int, required), productName (string, required), variationGroupMui[] (array, required) | {groupId: int} | When groupId is falsy, creates a new variation group and adds the product to it |
| POST | /api/variations/batchActionMoveVariationValues | currentGroupId (int, required), targetGroupId (int, required), variationValueIds[] (array, required) | {} | Move variation values from one group to another |
| POST | /api/variations/changeVariationGroupProductsPriority | variationProducts[] (array, required) | {} | Update display priority/sort order for products within a variation group |
| POST | /api/variations/batchActionMassDeleteValues | variationValueIds[] (array, required) | {} | Batch delete variation values |
| POST | /api/variations/updateProductVariationGroupNameMui | groupId (int, required), variationGroupMui[] (array, required) | {} | Update multi-language names for a variation group |
| POST | /api/variations/updateProductStock | productId (int, required), productCodeId (int, required), stock (int, required) | {} | Update stock for a specific product SKU |
| POST | /api/variations/getVariationByVariationValueId | variationValueId (int, required) | [{...}] | Get variation details by variation value ID |
Error format: {error: {field: message}, statusCode: 400, statusMsg: "Bad Request"} for validation failures; 422 for business rule violations.
Related Flows
- CF-01 Product Browsing — variation sidebar filter
- CF-02 Product Detail — variation matrix on PDP
- CF-04 Search — variation filters in search results
- CF-05 Cart — cart stores specific
productCodeId(SKU) - AD-16 Variations Admin — admin management of groups, values, and product assignments
- AD-17 Lines Admin — admin management of product codes/SKUs