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

Assortment Bundle Laravel Package

sylius/assortment-bundle

Sylius Assortment Bundle delivers the product catalog domain for Sylius e-commerce, modeling products, variants, options, and taxonomy with Doctrine and Symfony integration. It lets teams build flexible, variant-aware assortments and manage catalog data for online stores and sales channels.

View on GitHub
Deep Wiki
Context7

Getting Started

This is not a Laravel package. sylius/assortment-bundle is a Symfony 2 bundle from the pre-1.0 Sylius era, archived, with PHP 5.x era constraints and a Doctrine ORM domain model wired into Symfony's DI container. Installing it in a modern Laravel app will fail on composer require before you write a line of code, and even if you force it, there is no service provider, no Eloquent mapping, and no maintained branch.

Treat the repository as a domain-model reference, not a dependency.

Minimal steps that actually pay off:

  1. Read the source on GitHub, not Packagist. Start in Model/ for Product, Variant, Option, OptionValue, Property, and the master-variant concept.
  2. Look at the Doctrine mapping files (Resources/config/doctrine/*.orm.xml or YAML) to see the intended cardinalities: product → many variants, variant ↔ many option values, product → many properties.
  3. Look at the manager/service classes and the bundle's DependencyInjection/Configuration.php to see which classes were designed to be swappable.
  4. Translate the model to Eloquent in a fresh migration before writing any business logic.

First use case: you are building a catalog where a t-shirt has size and color, and you need one SKU per combination. Copy the relationship shape from this bundle into four or five Laravel migrations, then discard the rest. That is the highest-value 30 minutes you will get from this package.

If you genuinely must run it (legacy Symfony 2 app), note it is archived and pinned to EOL Symfony/PHP versions. Budget for a rewrite, not an upgrade.

Implementation Patterns

1. Port the schema, not the code. The value is the normalized model. A minimal Eloquent translation:

// products: id, name, slug, ...
// variants: id, product_id, sku, price, is_master
// options: id, product_id, name        (Size, Color)
// option_values: id, option_id, value  (S, M, L / Red, Blue)
// variant_option_value: variant_id, option_value_id
// properties: id, name, type           (Brand, Material — descriptive, not variant-defining)
// product_property: product_id, property_id, value

The distinction the bundle gets right and most homegrown catalogs get wrong: options drive variant generation; properties are descriptive metadata. Do not model "Brand" as an option unless you want one SKU per brand.

2. Variant generation as a service. The bundle's cartesian-product semantics are worth reimplementing directly:

class VariantGenerator
{
    public function generate(Product $product, array $optionValueIds): Collection
    {
        $optionValues = OptionValue::whereIn('id', $optionValueIds)->get()
            ->groupBy('option_id');

        $combinations = collect([[]]);
        foreach ($optionValues as $values) {
            $combinations = $combinations->crossJoin($values->all());
        }

        return $combinations->map(function (array $combo) use ($product) {
            return DB::transaction(function () use ($product, $combo) {
                $variant = $product->variants()->create([
                    'sku' => $this->skuFor($product, $combo),
                    'is_master' => false,
                ]);
                $variant->optionValues()->sync(collect($combo)->pluck('id'));
                return $variant;
            });
        });
    }
}

Keep the master variant (the bundle's default purchasable entity when a product has no options) as a boolean flag on variants, and enforce exactly one per product with a partial unique index or a model observer.

3. Wrap the domain in repositories/managers, mirroring the bundle's manager layer. The original had ProductManager-style services precisely so controllers stayed thin. In Laravel that means a CatalogService or repository, not fat models:

class ProductManager
{
    public function createWithVariants(array $data, array $optionValueIds): Product { /* ... */ }
    public function findPurchasableBySku(string $sku): ?Variant { /* ... */ }
}

This keeps the option/property logic out of controllers and makes it testable without HTTP.

4. Integration tip — don't bridge containers. If you need the bundle's behavior alongside Laravel, do not attempt to boot a Symfony kernel inside Laravel. Extract the model and reimplement. If you're in a mixed environment, run the Symfony app as a separate service and expose catalog reads over HTTP, then consume it from Laravel with a thin client. Anything else is a maintenance sink.

Gotchas and Tips

  • Archived means archived. No security releases, no PHP 8 compatibility work, no Symfony 5/6/7 support. The repository's own dependency constraints will block modern installs. Check with composer why-not sylius/assortment-bundle before spending time on an install attempt.
  • Zero dependents is a signal, not a bug. No one is maintaining an integration path for you. Issues and PRs are closed.
  • Doctrine ≠ Eloquent. The bundle leans on Doctrine's mapping and, in places, single-table inheritance and lifecycle callbacks. There is no mechanical translation. Re-model the relationships by hand; do not try to generate Eloquent from the ORM XML and expect the semantics to survive.
  • The master variant is easy to get wrong. Products without options still need a purchasable variant. If you omit it, pricing and cart logic breaks for simple products. Enforce "exactly one master per product" at the database level.
  • Uniqueness on option combinations. The original model allows duplicate variants if you don't add a constraint. Add a unique index on (product_id, sorted_option_value_ids_hash) or compute a deterministic hash column when generating variants.
  • Properties are not options. Repeated confusion in forks: putting "Color" in both tables creates two sources of truth and filtering bugs. Pick one home for each attribute.
  • Locale and taxonomy live elsewhere. Translation and taxon/category handling were separate Sylius bundles. Don't expect this package to give you either; you'll be writing them yourself.
  • If you do run it in legacy Symfony, the intended extension point was class overrides via bundle configuration (e.g. swapping the Product model class in config.yml). That pattern is worth copying conceptually — store model class names in config so a future fork can swap implementations — but it does not map to Laravel's container.
  • Opportunity vs. quality. The domain design is genuinely useful and small enough to port in a day; the artifact is not. Score the learning, not the dependency. Fork the ideas, pin your own implementation, and add tests around variant generation and master-variant invariants — those are the two places this model breaks in production.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle