Execution Flows
Step-by-step traces of key configurable product operations
Step-by-step traces of key configurable product operations
When a customer selects options and adds a configurable product to cart, the system must resolve the specific child product and create appropriate quote items.
POST request with super_attribute array containing selected option values.
super_attribute[93] = 49 (Color: Black), super_attribute[141] = 166 (Size: S)
Magento\Checkout\Controller\Cart\Add::execute()
Creates DataObject buyRequest with product ID and super_attribute data.
Magento\Quote\Model\Quote::addProduct()
Calls product type's prepareForCartAdvanced() method.
Magento\ConfigurableProduct\Model\Product\Type\Configurable::prepareForCartAdvanced()
Validates super_attribute values exist and are valid options.
getProductByAttributes($superAttributeValues, $product)
Finds the specific simple product matching the selected attribute combination.
PLUGIN CartConfiguration\Plugin\Configurable may intercept.
Checks child product is salable (in stock, enabled, valid dates).
Returns error message if child is not available.
Returns array: [0 => $parentProduct, 1 => $childProduct]
Both products are added to quote with parent-child relationship.
Two quote items created with parent_item_id linking child to parent.
Custom options stored in quote_item_option table.
PLUGIN QuantityValidator validates against child stock.
Quote recalculates totals using child product's price.
EVENT sales_quote_product_add_after
// Example buyRequest for configurable product
$buyRequest = new DataObject([
'product' => 123, // Configurable product ID
'qty' => 1,
'super_attribute' => [
93 => 49, // Color (attr_id) => Black (option_id)
141 => 166 // Size (attr_id) => Small (option_id)
]
]);
// Result from prepareForCartAdvanced()
$result = [
0 => $configurableProduct, // Parent (display item)
1 => $simpleProduct // Child (actual item for fulfillment)
];
In the cart, only the parent configurable product is visible. The child simple product is hidden (is_virtual = 1 on parent item). The child's SKU and stock are used for inventory, but the parent's name and image are displayed.
Configurable products display prices based on their child products. The frontend typically shows "From $X" or a price range.
Magento\Catalog\Pricing\Render\FinalPriceBox::renderAmount()
Triggers price info resolution for the configurable product.
$product->getPriceInfo()->getPrice('final_price')
Uses configurable-specific price collection from DI configuration.
Magento\ConfigurableProduct\Pricing\Price\FinalPrice::getValue()
Delegates to ConfigurablePriceResolver for actual resolution.
ConfigurablePriceResolver::resolvePrice()
Gets lowest price among all salable child products.
LowestPriceOptionsProvider::getProducts()
Queries indexed price data for children, filtered by stock status.
PLUGIN SalableResolver filters out-of-stock children.
ConfigurableOptionsCompositeFilter::filter()
Applies any configured filters (stock, visibility, etc.).
Returns the lowest final_price among filtered children.
Used for "From $X" display or tier pricing logic.
// Price resolution chain (di.xml virtual types)
// 1. FinalPrice uses ConfigurableFinalPriceResolver
FinalPrice
-> ConfigurableFinalPriceResolver (virtual type)
-> FinalPriceResolver (inner resolver)
-> resolvePrice($product)
// 2. LowestPriceOptionsProvider builds query
SELECT entity_id, min_price, final_price
FROM catalog_product_index_price
WHERE entity_id IN ($childIds)
AND customer_group_id = $groupId
AND website_id = $websiteId
ORDER BY final_price ASC
LIMIT 1
Configurable product pricing relies heavily on the catalog_product_index_price table. If the price indexer is out of date, displayed prices may be incorrect. The configurable indexer creates entries based on the minimum child price.
The product detail page loads a JSON structure containing all option combinations and their prices for the swatch/dropdown JavaScript.
Magento\ConfigurableProduct\Block\Product\View\Type\Configurable::getJsonConfig()
Called from product view template.
getAllowProducts() returns salable child products.
Filtered by stock status, visibility, and enabled status.
getOptionPrices() builds price data per child.
getOptions() builds attribute/option structure.
For each child, includes image gallery data if configured.
Enables image swapping when customer selects options.
Complete JSON structure for Magento_ConfigurableProduct/js/configurable
// Example JSON config structure
{
"attributes": {
"93": { // Color attribute ID
"id": "93",
"code": "color",
"label": "Color",
"options": [
{
"id": "49",
"label": "Black",
"products": ["456", "457", "458"] // Child IDs with this color
},
{
"id": "50",
"label": "Blue",
"products": ["459", "460", "461"]
}
]
}
},
"optionPrices": {
"456": { // Child product ID
"finalPrice": {"amount": 29.99},
"basePrice": {"amount": 29.99},
"oldPrice": {"amount": 39.99}
}
},
"images": {
"456": [{"img": "/media/catalog/product/t-shirt-black.jpg"}]
}
}
When saving a configurable product via repository or admin, the extension attributes for options and links are processed.
Product save initiated with extension_attributes containing configurable data.
configurable_product_options and configurable_product_links
Magento\ConfigurableProduct\Model\Plugin\ProductRepositorySave::afterSave()
PLUGIN sortOrder: 10
Magento\ConfigurableProduct\Model\Product\SaveHandler::execute()
Processes configurable-specific data after main product save.
Inserts/updates catalog_product_super_attribute table.
Saves store-specific labels to catalog_product_super_attribute_label.
Updates catalog_product_super_link table.
Validates child products have required attribute values.
Price and stock indexers scheduled for update.
PLUGIN UpdateStockChangedAuto syncs stock status.
// Saving configurable product with extension attributes
$product->setTypeId('configurable');
// Set configurable options (super attributes)
$optionFactory = $objectManager->get(OptionInterfaceFactory::class);
$option = $optionFactory->create();
$option->setAttributeId(93); // Color attribute
$option->setLabel('Color');
$option->setPosition(0);
$extensionAttributes = $product->getExtensionAttributes();
$extensionAttributes->setConfigurableProductOptions([$option]);
$extensionAttributes->setConfigurableProductLinks([456, 457, 458]); // Child IDs
$productRepository->save($product);
During checkout, configurable quote items are converted to order items while preserving the parent-child relationship.
Magento\Quote\Model\Quote\Item\ToOrderItem::convert()
Processes each quote item including configurable parent and simple child.
Magento\ConfigurableProduct\Model\ProductOptionProcessor::convertToProductOption()
Converts quote item options to order item options.
Parent order item created with child's data for fulfillment.
Selected options stored in product_options JSON column.
Inventory deducted from the simple child product, not the configurable parent.
Configurable products have no independent stock.
// Order item product_options JSON structure
{
"info_buyRequest": {
"product": 123,
"super_attribute": {"93": "49", "141": "166"},
"qty": 1
},
"attributes_info": [
{"label": "Color", "value": "Black"},
{"label": "Size", "value": "Small"}
],
"simple_name": "T-Shirt Black Small",
"simple_sku": "TSHIRT-BLK-S"
}
While the order displays the configurable product name, the simple_sku in product_options is used for fulfillment. Warehouse management systems should reference this SKU, not the parent configurable SKU.
A configurable product's stock status is derived from its children. If any child is in stock, the parent is considered salable.
Magento\ConfigurableProduct\Model\Product\Type\Configurable::isSalable()
getSalableUsedProducts($product)
Filters children by isSalable() check.
Returns true if at least one child is salable.
Returns false if all children are out of stock.
When a child product's stock changes, the UpdateStockChangedAuto plugin triggers reindex of the parent configurable product's stock status. This ensures the configurable shows as out-of-stock when all children are depleted.