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().
StreamedResponse to avoid memory spikes.array_product or nested loops are less efficient for large datasets and lack lazy evaluation.composer require installation with zero configuration. No service providers, facades, or Laravel-specific bootstrapping is needed.expect()->iteratesOver() or by asserting individual tuples.Memory facade or memory_get_usage()).| Risk Area | Assessment | Mitigation Strategy |
|---|---|---|
| Memory Management | While the iterator design is memory-efficient, toArray() could cause spikes for large datasets. |
Enforce lazy evaluation in public APIs; document and enforce usage guidelines (e.g., "Use iterators for >1000 combinations"). |
| Performance Overhead | Iterator overhead may impact small datasets (<100 items). | Benchmark against native solutions; optimize for use cases with ≥1000 combinations. |
| Thread Safety | Stateless iterators are thread-safe, but concurrent toArray() calls may race. |
Restrict toArray() to single-threaded contexts; use iterators in async/parallel processing. |
| Laravel-Specific Quirks | No direct conflicts, but integration with Laravel’s event loop or queues may require testing. | Test with Laravel’s queue workers and async contexts (e.g., dispatch()). |
| Input Validation | Currently returns an empty iterator for invalid inputs (e.g., non-array). | Add input validation (e.g., assertAllArrays()) or throw exceptions for invalid data. |
CartesianProduct::query() for Eloquent or a collection macro)?Collection class for chaining methods (e.g., filter(), map(), chunk()).CartesianProduct → dispatch()).StreamedResponse or SynchronousQueue to avoid memory issues.expect()->iteratesOver() or assertions on individual tuples.CartesianProduct::fake() or stubs).Memory facade or memory_get_usage() to validate efficiency.Pilot Phase:
Core Integration:
app/Services/CartesianProductService) to standardize usage and add Laravel-specific logic.
namespace App\Services;
use Nerd\CartesianProduct\CartesianProduct;
class CartesianProductService {
public function generateCombinations(array $arrays): \Generator {
return CartesianProduct::of($arrays);
}
public function toArray(array $arrays): array {
return CartesianProduct::of($arrays)->toArray();
}
public function streamCombinations(array $arrays): \Generator {
yield from CartesianProduct::of($arrays);
}
}
AppServiceProvider:
public function register(): void {
$this->app->singleton(CartesianProductService::class);
}
Laravel-Specific Extensions:
Collection class for fluent integration:
use Illuminate\Support\Collection;
Collection::macro('cartesian', function ($arrays) {
return $this->pipe(fn ($collection) => CartesianProduct::of($arrays));
});
Usage:
$combinations = collect([])->cartesian([['a', 'b'], ['c', 'd']]);
use Illuminate\Database\Eloquent\Builder;
trait CartesianQueryBuilder {
public function withCombinations(array $arrays): Builder {
$combinations = CartesianProduct::of($arrays)->toArray();
// Build dynamic where clauses or joins
return $this->where(function ($query) use ($combinations) {
foreach ($combinations as $combination) {
$query->orWhere($this->buildCombinationConditions($combination));
}
});
}
}
StreamedResponse to return large result sets without memory issues:
use Symfony\Component\HttpFoundation\StreamedResponse;
return new StreamedResponse(function () {
$combinations = CartesianProduct::of([['a', 'b'], ['c', 'd']]);
foreach ($combinations as $combination) {
echo json_encode($combination) . "\n";
}
}, 200, ['Content-Type' => 'application/json']);
Async Processing:
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class GenerateCombinationsJob implements ShouldQueue {
use Dispatchable, Queueable;
public function handle(): void {
$combinations = CartesianProduct::of([/* large arrays */]);
How can I help you explore Laravel packages today?