php-standard-library/range
Range types for integer sequences with built-in iteration support. Create, traverse, and manipulate numeric ranges with a clean, standard-library style API. Part of the PHP Standard Library project; see docs, contribute, or report issues on GitHub.
## Technical Evaluation
### **Architecture Fit**
- **Use Case Alignment**:
- **New `Range::chunk()` Method**: Introduces **memory-efficient chunking** for large ranges (e.g., `Range::from(1, 1_000_000)->chunk(1000)`), directly aligning with Laravel’s **chunked database queries** and **queue batch processing**. Reduces manual `for` loops with `Range::lazy()->chunk()`.
- **Immutable `Range::reverse()`**: Enables **descending ranges** (e.g., `Range::from(10, 1, -1)`), useful for **pagination** (`->orderBy('id', 'desc')`) and **reverse iteration** in collections.
- **Enhanced `lazy()` with `close()`**: Adds explicit iterator cleanup (e.g., `Range::lazy()->each(...)->close()`), critical for **avoiding memory leaks** in long-running Laravel processes (e.g., Horizon workers).
- **Type-Safe `Range::assertValid()`**: Now throws **descriptive exceptions** (e.g., `"Step cannot be zero"`), improving debugging in Laravel’s **exception handlers** (e.g., `App\Exceptions\Handler`).
- **Laravel Synergy**:
- **Query Builder Integration**: New `whereBetweenRange()` method proposed for dynamic ranges:
```php
User::whereBetweenRange('id', 1, 100, 2) // WHERE id BETWEEN 1 AND 100 AND id % 2 = 0
```
- **Collection Macros**: Extended with `chunkRange()` for fluent syntax:
```php
collect()->chunkRange(1, 100, 10)->each(fn($chunk) => ...);
```
- **Testing**: Supports **data seeding** with stepped ranges:
```php
factory(User::class, Range::from(1, 50, 2)->count())->create();
```
- **Anti-Patterns**:
- **Overhead for Trivial Cases**: Still avoids micro-optimizations for simple loops (e.g., `for ($i = 0; $i < 5; $i++)`).
- **Lazy Evaluation Complexity**: Requires explicit `close()` calls, adding cognitive load. Mitigate with **context managers** (e.g., `try-catch-finally` blocks).
### **Integration Feasibility**
- **Laravel Compatibility**:
- **No Breaking Changes**: Backward-compatible with 6.1.1; additive features only.
- **PSR-4/PSR-12**: Adheres to Laravel’s standards; zero conflicts.
- **Type Hints**: Fully compatible with PHP 8.1+ (Laravel’s baseline); leverages `Iterator` and `Closure` types.
- **Key New Features for Laravel**:
```php
// Chunked lazy ranges for batch processing
Range::from(1, 1_000_000)->lazy()->chunk(500)->each(function ($chunk) {
User::whereIn('id', $chunk)->update(['status' => 'processed']);
});
// Reverse ranges for descending queries
$descendingIds = Range::from(100, 1, -1)->toArray();
User::whereIn('id', $descendingIds)->orderBy('id', 'desc')->get();
// Explicit iterator cleanup in queue jobs
Range::from(1, 1000)->lazy()->each(fn($id) => dispatch(new ProcessUser($id)))
->close(); // Prevents memory leaks in Horizon
Range::lazy() now requires explicit close() for iterators (documented as a best practice).memory_get_usage()).$range = Range::from(1, 1_000_000)->lazy();
try {
$range->each(...);
} finally {
$range->close();
}
"Step must not be zero"), reducing runtime errors.Range::chunk() work efficiently with Laravel’s cursor()? Test:
User::query()->cursor()->each(fn($user) => ...); // Compare to chunked ranges
Range::from(1, 1000)->lazy()->chunk(10)->parallel()->each(...);
Range objects be cached (e.g., Redis)? Test:
cache()->put('range', Range::from(1, 10)->chunk(2)); // May fail if not serializable
Iterator improvements and Range type enhancements.whereBetweenRange() and whereInRange() methods:
DB::table('users')->whereInRange('id', 1, 100, 2); // WHERE id IN (1, 3, 5, ...)
DB::table('users')->whereBetweenRange('id', 1, 100); // WHERE id BETWEEN 1 AND 100
chunkRange() and reverseRange() macros:
Collection::macro('chunkRange', function ($start, $end, $step = 1, $chunkSize = 100) {
return $this->merge(Range::from($start, $end, $step)->chunk($chunkSize)->toArray());
});
chunk() for memory-efficient batch jobs:
ProcessUsers::dispatch(Range::from(1, 1_000_000)->lazy()->chunk(1000));
Range (8.2+): Lacks chunk() and reverse(); package remains superior.chunk() vs. native chunk() for memory usage:
php -d memory_limit=512M benchmark_chunking.php
reverse() in query scenarios (e.g., descending pagination).lazy() usage for missing close() calls.composer.json (if not already present):
"require": {
"php-standard-library/range": "^6.1.2"
}
RangeService facade with context managers:
facade(RangeService::class);
RangeService::chunk(1, 1000, 100)->each(...)->close();
chunk() and reverse().whereInRange().Range for dynamic UI ranges.disallow_for_loops with exceptions for Range).Range type or Iterator improvements).chunk() in memory-intensive jobs and reverse() for queries.close() explicitly in lazy() usage incrementally.How can I help you explore Laravel packages today?