Grouped Products
Grouped Product Overview
Grouped products are collections of simple products sold together:
Kitchen Set (Grouped):
├── Pot → $29.99
├── Pan → $24.99
├── Utensils → $14.99
└── Towel → $9.99
Customer can buy any combination
Grouped Product Structure
-- Parent grouped product
SELECT entity_id, sku, type_id
FROM catalog_product_entity
WHERE entity_id = 200;
+-----------+-------------+--------+
| entity_id | sku | type_id|
+-----------+-------------+--------+
| 200 | KITCHEN-SET | grouped |
+-----------+-------------+--------+
-- Associated products
SELECT * FROM catalog_product_link
WHERE link_type_id = 4 AND product_id = 200;
+----------+------------+---------------+
| link_id | product_id | linked_product_id |
+----------+------------+---------------+
| 789 | 200 | 201 |
| 790 | 200 | 202 |
| 791 | 200 | 203 |
| 792 | 200 | 204 |
+----------+------------+---------------+
Creating Grouped Product
// Create grouped product
$groupedProduct = $objectManager->get(
\Magento\Catalog\Model\ProductFactory::class
)->create();
$groupedProduct->setName('Kitchen Set')
->setSku('KITCHEN-SET')
->setPrice(0) // Grouped price is sum of options
->setStatus(1)
->setVisibility(4)
->setAttributeSetId(4)
->setTypeId('grouped')
->setStockData(['is_in_stock' => 1])
->save();
// Add associated products
$associatedProducts = [201, 202, 203, 204];
$groupedProduct->setAssociatedProductIds($associatedProducts);
$groupedProduct->save();
Grouped Product Pricing
Grouped product price = Sum of selected options
Kitchen Set:
Pot (1x $29.99) = $29.99
Pan (1x $24.99) = $24.99
Utensils (1x $14.99) = $14.99
Towel (1x $9.99) = $9.99
------------------------
Total = $79.96
Customer can adjust quantities for each item
Bundle Products
Bundle Product Overview
Bundle products are customizable sets with fixed options:
Custom Laptop (Bundle):
CPU: Intel i5 ($0) or Intel i7 (+$200) [Required, Single]
RAM: 8GB ($0) or 16GB (+$100) [Required, Single]
Storage: 256GB ($0) or 512GB (+$150) [Required, Single]
Software: Office (+$150) or None ($0) [Optional, Multiple]
Bundle Product Structure
-- Parent bundle product
SELECT entity_id, sku, type_id
FROM catalog_product_entity
WHERE entity_id = 300;
+-----------+----------+--------+
| entity_id | sku | type_id|
+-----------+----------+--------+
| 300 | LAPTOP | bundle |
+-----------+----------+--------+
-- Bundle options
SELECT * FROM catalog_product_bundle_option WHERE product_id = 300;
+----------+------------+------+--------+--------+
| option_id| product_id | type | required| position|
+----------+------------+------+--------+--------+
| 1 | 300 | radio| 1| 1|
| 2 | 300 | radio| 1| 2|
| 3 | 300 | radio| 1| 3|
| 4 | 300 | check| 0| 4|
+----------+------------+------+--------+--------+
-- Bundle selections (option values)
SELECT * FROM catalog_product_bundle_selection WHERE option_id IN (1,2,3,4);
+---------------+-----------+------------+--------+
| selection_id | option_id | product_id | position|
+---------------+-----------+------------+--------+
| 1 | 1 | 301 | 1|
| 2 | 1 | 302 | 2|
| 3 | 2 | 303 | 1|
| 4 | 2 | 304 | 2|
| 5 | 3 | 305 | 1|
| 6 | 3 | 306 | 2|
| 7 | 4 | 307 | 1|
| 8 | 4 | 308 | 2|
+---------------+-----------+------------+--------+
Creating Bundle Product
// Create bundle product
$bundleProduct = $objectManager->get(
\Magento\Catalog\Model\ProductFactory::class
)->create();
$bundleProduct->setName('Custom Laptop')
->setSku('LAPTOP')
->setPriceType(1) // 1=DYNAMIC, 0=FIXED
->setPriceView(0) // 0=As low as, 1=Range
->setStatus(1)
->setVisibility(4)
->setAttributeSetId(4)
->setTypeId('bundle')
->setStockData(['is_in_stock' => 1])
->save();
// Add options and selections
$bundleOptions = [
[
'title' => 'CPU',
'type' => 'radio',
'required' => 1,
'position' => 1,
'selections' => [
['product_id' => 301, 'position' => 1, 'price' => 0],
['product_id' => 302, 'position' => 2, 'price' => 200],
]
],
// ... more options
];
$bundleProduct->setBundleOptionsData($bundleOptions);
$bundleProduct->save();
Bundle Pricing
Price Types
// Dynamic pricing (based on selected options)
$bundleProduct->setPriceType(1);
// Price = Sum of selected option prices
// Fixed pricing (pre-set price)
$bundleProduct->setPriceType(0);
$bundleProduct->setPrice(999.99);
// Price = Fixed, options don't affect total
Price Calculation
Dynamic Pricing:
Base laptop: $0
CPU i7: +$200
RAM 16GB: +$100
Storage 512GB: +$150
Office: +$150
----------------
Total: $600
Fixed Pricing:
Bundle price: $999.99 (regardless of options)
Price Display
// Get bundle price
$priceInfo = $bundleProduct->getPriceInfo();
// Dynamic: get price for specific options
$price = $priceInfo->getPrice('final_price')->getValue();
// Fixed: get base price
$price = $bundleProduct->getPrice();
// Display on frontend
// "As low as $600.00" (dynamic)
// "Bundle Price: $999.99" (fixed)
Option Price Sources
Option pricing can come from:
1. Custom price (set in bundle configuration)
2. Product price (use child product price)
3. Percent (percentage of parent price)
Example:
Option: CPU
Selection: Intel i5 → Price: $0 (free upgrade)
Selection: Intel i7 → Price: $200 (custom price)
Option: RAM
Selection: 8GB → Price: $0 (use product price)
Selection: 16GB → Price: 10% (10% of parent price)
Inventory for Both Types
Grouped Product Inventory
// Grouped product stock (not tracked)
$groupedProduct->setStockData([
'is_in_stock' => 1,
'manage_stock' => 0,
]);
// Associated product stock (tracked individually)
$associatedProduct->setStockData([
'qty' => 50,
'is_in_stock' => 1,
'manage_stock' => 1,
]);
// Stock status logic
// Grouped product is in stock if ANY associated product is in stock
Bundle Product Inventory
// Bundle product stock
$bundleProduct->setStockData([
'is_in_stock' => 1,
'manage_stock' => 0,
'stock_status_changed_auto' => 0,
]);
// Selection product stock (tracked)
$selectionProduct->setStockData([
'qty' => 100,
'is_in_stock' => 1,
'manage_stock' => 1,
]);
// Stock status logic
// Bundle product is in stock if ALL required options have in-stock selections
Use Cases Comparison
| Feature | Grouped | Bundle |
|---|---|---|
| Price | Sum of options | Dynamic or Fixed |
| Selection | Customer chooses qty | Customer chooses options |
| Required options | All optional | Mix of required/optional |
| Stock | Per item | Per selection |
| Use case | Kitchen set, gift basket | Custom laptop, meal combo |
| Flexibility | Any quantity per item | Fixed option structure |
Best Practices
Grouped:
- Use for similar products sold together
- Set reasonable default quantities
- Consider bundle instead if options are required
Bundle:
- Use for customizable products
- Mark required options clearly
- Set appropriate default selections
- Test all option combinations
- Consider dynamic pricing for flexibility
Quiz
1. What is a grouped product?
2. What is the difference between dynamic and fixed bundle pricing?
3. When is a grouped product in stock?
Flashcards
Question
What is a grouped product?
Click to reveal answer
Answer
Collection of simple products sold together, customer chooses quantities
Question
What is a bundle product?
Click to reveal answer
Answer
Customizable product with options (required/optional) and selections
Question
How is grouped pricing calculated?
Click to reveal answer
Answer
Sum of selected option prices based on quantities
Question
What is dynamic bundle pricing?
Click to reveal answer
Answer
Price changes based on selected options
Question
What is fixed bundle pricing?
Click to reveal answer
Answer
Price remains constant regardless of options
Revision Notes
Key Takeaways
- 1. Grouped products: collections of simple products, customer chooses quantities
- 2. Bundle products: customizable with options and selections
- 3. Grouped price = sum of selected options × quantities
- 4. Bundle pricing: dynamic (varies) or fixed (constant)
- 5. Stock: both types track stock on child/selection products
Interview Tips
- • Compare grouped vs bundle product use cases
- • Explain dynamic vs fixed bundle pricing
- • Discuss inventory management for both types
Cheat Sheet
Grouped Product:
type_id = 'grouped'
Collection of simple products
Price = Sum of options × quantities
Stock: in stock if ANY item in stock
Bundle Product:
type_id = 'bundle'
Customizable options + selections
Price: dynamic (1) or fixed (0)
Required/optional options
Stock: in stock if ALL required options have stock
Tables:
catalog_product_link (type=4) → Grouped associations
catalog_product_bundle_option → Bundle options
catalog_product_bundle_selection → Bundle selections