Weave Code
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

Cartesian Product Laravel Package

th3n3rd/cartesian-product

Memory-efficient Cartesian Product generator for PHP. Uses iterators to yield one tuple at a time, letting you handle very large combinations without big memory usage. Build products via fluent with() calls or CartesianProduct::of(), iterate or toArray().

View on GitHub
Deep Wiki
Context7

Getting Started

To begin using th3n3rd/cartesian-product in Laravel, install the package via Composer:

composer require th3n3rd/cartesian-product

First Use Case: Generating Product Variants

A common Laravel use case is generating product variants for an e-commerce platform. Start with a simple example:

use Nerd\CartesianProduct\CartesianProduct;

// Define product attributes
$attributes = [
    'size' => ['S', 'M', 'L'],
    'color' => ['red', 'blue', 'green'],
    'material' => ['cotton', 'polyester']
];

// Create Cartesian product
$cartesianProduct = CartesianProduct::of($attributes);

// Iterate and create variants (memory-efficient)
foreach ($cartesianProduct as $variant) {
    \App\Models\ProductVariant::create([
        'size' => $variant[0],
        'color' => $variant[1],
        'material' => $variant[2],
    ]);
}

Where to Look First

  • README.md: Focus on the Usage section for basic syntax (CartesianProduct::of() vs. empty()->with()).
  • Source Code: Explore src/CartesianProduct.php for iterator logic and edge-case handling.
  • Laravel Integration: Check if your use case requires wrapping the static factory in a service provider for DI compatibility.

Implementation Patterns

Core Workflows

1. Dynamic Variant Generation

Use the fluent API to build products incrementally:

$productBuilder = CartesianProduct::empty();
$productBuilder->with(['size' => ['S', 'M', 'L']]);
$productBuilder->with(['color' => ['red', 'blue']]);

// Process in batches (e.g., per request or queue job)
foreach ($productBuilder as $variant) {
    // Process $variant (e.g., create records, generate URLs)
}

2. Integration with Laravel Collections

Combine with Laravel’s Collection for additional processing:

use Illuminate\Support\Collection;

$variants = collect(CartesianProduct::of([
    ['size' => ['S', 'M']],
    ['color' => ['red', 'blue']],
]));

// Group by size
$grouped = $variants->groupBy('size');

3. Queue-Based Processing

Offload memory-intensive operations to Laravel queues:

use Illuminate\Support\Facades\Queue;

$attributes = [
    'size' => ['S', 'M', 'L', 'XL'],
    'color' => ['red', 'blue', 'green', 'black'],
];

Queue::push(function () use ($attributes) {
    $cartesian = CartesianProduct::of($attributes);
    foreach ($cartesian as $variant) {
        \App\Models\ProductVariant::create($variant);
    }
});

4. API Response Generation

Generate dynamic API responses (e.g., for filtering):

$filters = [
    'price_range' => ['0-50', '50-100', '100+'],
    'category' => ['electronics', 'clothing'],
];

$combinations = CartesianProduct::of($filters)->toArray();
return response()->json(['filters' => $combinations]);

Laravel-Specific Patterns

Service Provider Wrapper

To integrate with Laravel’s DI container, create a wrapper:

// app/Providers/CartesianProductServiceProvider.php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Nerd\CartesianProduct\CartesianProduct;

class CartesianProductServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->bind(CartesianProduct::class, function () {
            return new CartesianProduct();
        });
    }
}

Eloquent Relationships

Use Cartesian products to generate related models:

// In a Product model
public function variants()
{
    $attributes = [
        'size' => $this->sizes,
        'color' => $this->colors,
    ];

    return $this->hasMany(ProductVariant::class)
        ->whereIn('size', $attributes['size'])
        ->whereIn('color', $attributes['color']);
}

// Then use CartesianProduct to validate or generate missing variants

Dynamic Route Generation

Generate routes for all product combinations:

$routes = [];
foreach (CartesianProduct::of([
    ['size' => ['S', 'M']],
    ['color' => ['red', 'blue']],
]) as $params) {
    $routes[] = route('products.show', $params);
}

Gotchas and Tips

Pitfalls

  1. Memory Leaks with toArray()

    • Avoid calling toArray() on large datasets (e.g., >1,000 combinations) as it materializes all results in memory.
    • Fix: Always iterate lazily with foreach or use chunking.
  2. Static Factory Conflicts

    • The package’s static methods (CartesianProduct::of()) bypass Laravel’s DI container.
    • Fix: Use a service provider wrapper (as shown above) or instantiate manually:
      $cartesian = new \Nerd\CartesianProduct\CartesianProduct();
      $cartesian->with([...]);
      
  3. Empty Array Handling

    • Passing an empty array to with() or of() may not behave as expected.
    • Fix: Validate inputs:
      $arrays = array_filter($inputArrays, fn($arr) => !empty($arr));
      $cartesian = CartesianProduct::of($arrays);
      
  4. Recursion Depth Limits

    • Very large input arrays (e.g., >20) may hit PHP’s recursion limit.
    • Fix: Use iterative approaches or split inputs into batches.
  5. Laravel Queue Timeouts

    • Long-running Cartesian iterations may exceed queue job timeouts.
    • Fix: Process in chunks or use database-backed queues.

Debugging Tips

  • Memory Profiling: Use Laravel Telescope or Xdebug to monitor memory usage during iteration.
  • Iterator Validation: Verify the iterator yields the expected number of combinations:
    $count = 0;
    foreach ($cartesian as $item) $count++;
    dd($count); // Should equal product of input array sizes
    
  • Edge Cases: Test with:
    • Empty arrays.
    • Arrays of varying lengths.
    • Arrays with duplicate values.

Extension Points

  1. Custom Iterators Extend the base CartesianProduct class to add Laravel-specific logic:

    class LaravelCartesianProduct extends CartesianProduct
    {
        public function toCollection()
        {
            return collect(iterator_to_array($this));
        }
    }
    
  2. Caching Layer Cache Cartesian products for repeated use (e.g., product variants):

    $cacheKey = 'product_variants_' . md5(serialize($attributes));
    $variants = Cache::remember($cacheKey, now()->addHours(1), function () use ($attributes) {
        return CartesianProduct::of($attributes)->toArray();
    });
    
  3. Event Dispatching Trigger events during iteration (e.g., for analytics):

    foreach ($cartesian as $variant) {
        event(new VariantGenerated($variant));
        // ...
    }
    
  4. Database Integration Use the iterator to bulk insert variants:

    DB::table('product_variants')->insert(
        iterator_to_array($cartesian)
    );
    

Performance Optimization

  • Chunk Processing: Process large Cartesian products in chunks:
    $chunkSize = 1000;
    $iterator = CartesianProduct::of($attributes);
    $chunk = [];
    foreach ($iterator as $item) {
        $chunk[] = $item;
        if (count($chunk) === $chunkSize) {
            Process::chunk($chunk);
            $chunk = [];
        }
    }
    if (!empty($chunk)) {
        Process::chunk($chunk);
    }
    
  • Parallel Processing: Use Laravel’s parallel helper for CPU-bound tasks:
    parallel([
        fn() => $this->processChunk($cartesian, 0, 500),
        fn() => $this->processChunk($cartesian, 500, 1000),
    ]);
    
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport