Creating Configurable Product Linked with Virtual Product in Magento Using Data Patch

In Magento, creating configurable products linked with virtual products involves several steps to ensure the correct association and configuration. This process can be automated and encapsulated using data patches. Below is an example code snippet that demonstrates how to achieve this using PHP in a Magento module.

1. Create a Virtual Product

The createVirtualProduct function creates a virtual product with specified attributes. It sets the product type as virtual, assigns the attribute set, and sets custom attributes.

public function createVirtualProduct(AttributeSetInterface $attrSet): ProductInterface  
{
    // Create virtual product
    $virtualProduct = $this->createProduct(
        name: 'Virtual Product',
        sku: 'virtual_sku',
        typeId: Product\Type::TYPE_VIRTUAL,
        attributeSetId: (int)$attrSet->getAttributeSetId()
    );

    // Set custom attributes
    $attributes = [
        self::CONFIGURABLE_ATTRIBUTE => 0,
        'attribute_code' => 'attribute_value',
    ];

    foreach ($attributes as $attributeCode => $attributeLabel) {
        $attribute = $this->attributeRepository->get('catalog_product', $attributeCode);

        if ($attribute->usesSource()) {
            $optionId = $attribute->getSource()->getOptionId($attributeLabel);
            $virtualProduct->setCustomAttribute($attributeCode, $optionId);
            continue;
        }

        $virtualProduct->setCustomAttribute($attributeCode, $attributeLabel);
    }

    return $this->productRepository->save($virtualProduct);
}

2. Create Configurable Product

The createConfigurableProduct function creates a configurable product and associates it with the previously created virtual product. It sets the product type as configurable, defines configurable attributes, and links it to the virtual product.

public function createConfigurableProduct(
    AttributeSetInterface $attrSet,
    ProductInterface $virtualProduct
): void {
    // Create configurable product
    $configurableProduct = $this->createProduct(
        name: 'Configurable Product',
        sku: 'configurable_sku',
        typeId: Configurable::TYPE_CODE,
        attributeSetId: (int)$attrSet->getAttributeSetId()
    );

    // Get configurable attribute
    $configurableAttribute = $this->attributeRepository->get(Product::ENTITY, self::CONFIGURABLE_ATTRIBUTE);

    // Set configurable attributes
    $configurableProduct->getTypeInstance()->setUsedProductAttributeIds(
        [$configurableAttribute->getAttributeId()],
        $configurableProduct
    );

    $configurableAttributesData = $configurableProduct->getTypeInstance()->getConfigurableAttributesAsArray(
        $configurableProduct
    );

    $configurableProduct->setData('configurable_attributes_data', $configurableAttributesData);
    $configurableProduct->setAssociatedProductIds([$virtualProduct->getId()]);
    $configurableProduct->setData('can_save_configurable_attributes', true);

    $this->productRepository->save($configurableProduct);
}

This code demonstrates the process of creating a configurable product linked with a virtual product using data patches in Magento. It ensures that the association is correctly set up and attributes are configured as expected.