Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Variable Product Bundle Laravel Package

sylius/variable-product-bundle

Adds variable product support to Sylius, letting merchants create products with multiple options and variants and manage pricing, stock, and availability per variant. Integrates with the Sylius admin and storefront so configurable catalog items work out of the box.

View on GitHub
Deep Wiki
Context7

Getting Started

First, verify you actually need it. This bundle is archived and read-only. Product variants and options live inside sylius/sylius core for modern versions (roughly 1.12+ and Sylius 2.x). You only pull this bundle in if you're maintaining a legacy project whose composer.json already requires it, or you're studying how variant generation used to be structured. Check your Sylius version constraint first:

composer show sylius/sylius | grep versions
composer why sylius/variable-product-bundle

If nothing depends on it, do not install it. Modern code should use Sylius\Component\Core\Model\ProductVariant and the sylius.generator.product_variant service in core.

Minimal setup (legacy Sylius):

composer require sylius/variable-product-bundle

Register it in AppKernel / bundles.php before SyliusCoreBundle, then update the schema:

bin/console doctrine:schema:update --force
# or bin/console doctrine:migrations:diff

Where to look first, in this order:

  1. src/Model/ — ProductVariant, ProductOption, ProductOptionValue, their interfaces, and ProductVariantInterface relationships to ProductInterface.
  2. src/Resources/config/doctrine/*.orm.xml — the mapping that ties variants to products and options. This is where overrides break.
  3. src/Resources/config/services.xml — the services you can decorate (sylius.factory.product_variant, sylius.repository.product_variant, option repositories).
  4. src/Form/Type/ — ProductVariantType, ProductOptionType, ProductOptionValueType, and the variant selection form.

First use case: create a product ("T-shirt") with options Size and Color, add option values (S/M/L, Red/Blue), then generate the cartesian product of variants and render a selector on the product page. In a template, the selection typically ends up as a form posting optionValues[] which resolves to a single ProductVariant via the repository.

Implementation Patterns

Model extension via parameters (the standard Sylius pattern). Override the concrete classes in config.yml/services.yaml rather than editing the bundle:

parameters:
    sylius.model.product_variant.class: App\Entity\ProductVariant
    sylius.repository.product_variant.class: App\Repository\ProductVariantRepository

If you subclass ProductVariant, you must also repoint the Doctrine association's targetEntity or ensure ResolveTargetEntityListener maps Sylius\Component\VariableProductBundle\Model\ProductVariantInterface to your class. Forgetting this is the #1 source of "class not found" and wrong-class hydration errors.

Variant generation workflow. Use the generator service instead of hand-building combinations:

$generator = $this->get('sylius.generator.product_variant');
$generator->generate($product); // produces one ProductVariant per option-value combination

This is the pattern to reuse in fixtures, imports, and admin "generate variants" actions. Always persist after generation — the generator does not flush.

Fixtures for reproducible catalogs. Define options and variants in YAML and let sylius_fixtures handle it:

product:
    options:
        - name: Size
          values: [S, M, L]
        - name: Color
          values: [Red, Blue]
    variants:
        - code: TSHIRT-S-RED
          optionValues: [TSHIRT-S, TSHIRT-RED]

The optionValues key must reference option-value codes; silently empty variants are the usual symptom of a typo there.

Variant selector integration. Build a form with option-value choice fields, then resolve the selected combination to a variant through sylius.repository.product_variant using findOneByOptionValues() (or an equivalent custom query). Validate before rendering "add to cart" — a missing variant should produce a validation error, not a null object downstream.

Event hooks. Use sylius.product.pre_create / sylius.product.pre_update and the variant equivalents to enforce invariants (at least one variant, unique combinations) rather than overriding controllers.

Repository customization. Extend ProductVariantRepository for combination lookups and for eager-loading optionValues to avoid N+1 queries on listing pages.

Gotchas and Tips

  • Archived means no fixes. No PRs, no security patches, no issue triage. Any bug you find is yours to patch in a fork. Treat its transitive dependencies as your responsibility.
  • Version coupling is brittle. This bundle pins to specific Sylius minor versions. Installing it alongside a newer sylius/sylius usually produces composer conflict hell or subtle runtime mismatches. Confirm the exact pair from the bundle's own composer.json before touching the lockfile.
  • Duplicate combinations are not prevented. The unique constraint is on code, not on the option-value set. Two variants with identical option values are legal at the DB level and will confuse the selector. Enforce uniqueness in a pre_create/pre_update listener.
  • Deleting options doesn't cascade to variants. Removing a ProductOptionValue leaves variants referencing stale references (or FK errors, depending on mapping). Add cleanup logic or restrict deletion.
  • Translations are required for display. Option names and values are translatable; missing translations render blank labels in the selector. Use TranslatableListener conventions and always populate translations in fixtures.
  • Cartesian-product explosion. The generator multiplies option counts. Five options with five values each yields 3,125 variants, which cripples both generation and the selector. Cap options, paginate, or generate lazily.
  • Debugging commands that actually help:
    bin/console debug:container sylius.repository.product_variant
    bin/console debug:container --parameter=sylius.model.product_variant.class
    bin/console doctrine:schema:validate
    bin/console doctrine:query:sql "SELECT id, code FROM sylius_product_variant"
    
  • Mapping override footgun. When subclassing any model, run doctrine:schema:validate and check doctrine:mapping:info for duplicate entity mappings. Sylius loads XML mapping from the bundle; your override must not leave both mapped.
  • Form type extension points. Decorate sylius.form.type.product_variant to add fields rather than copying the form. For the front-end selector, the form type is separate and typically lives in your app, not the bundle.
  • Plan the migration. If you're on this bundle, map each class to its core equivalent (Sylius\Component\Core\Model\*) and rehearse the data migration on a copy. There is no supported upgrade path from a read-only bundle; write your own and test on real data volume.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route