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

Range Laravel Package

php-standard-library/range

Range types for integer sequences with iteration support, part of the PHP Standard Library. Provides typed, iterable integer ranges for clean sequence generation in PHP applications. Install via Composer and use alongside other php-standard-library packages.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require php-standard-library/range
    

    Add to composer.json under require:

    "php-standard-library/range": "^6.2"
    
  2. First Use Case: Replace a manual loop with a Range object:

    use PHPStandardLibrary\Range\Range;
    
    // Before: Manual loop
    for ($i = 1; $i <= 10; $i++) {
        echo $i;
    }
    
    // After: Range iteration
    foreach (Range::from(1, 10) as $i) {
        echo $i;
    }
    
  3. Key Classes:

    • Range: Core class for integer sequences.
    • LazyRange: Memory-efficient iterator for large ranges (e.g., batch processing).
    • RangeException: Handle invalid ranges (e.g., start > end).
  4. Where to Look First:

    • Documentation for API reference.
    • src/Range.php for core methods (e.g., from(), step(), lazy()).
    • tests/ for usage examples and edge cases.

Implementation Patterns

Core Workflows

1. Basic Range Creation

// Inclusive range (1–10)
$range = Range::from(1, 10);

// Exclusive range (1–9)
$range = Range::from(1, 10, 1, false);

// Step ranges (e.g., even numbers)
$evens = Range::from(2, 20, 2);

2. Lazy Evaluation for Large Datasets

Use lazy() to avoid memory issues (e.g., processing 1M+ records):

use PHPStandardLibrary\Range\LazyRange;

$lazyRange = Range::from(1, 1_000_000)->lazy();

foreach ($lazyRange as $id) {
    // Process one record at a time (memory-efficient)
    User::find($id)->update(['status' => 'processed']);
}

3. Integration with Laravel Collections

Combine with Laravel’s Collection for functional operations:

use Illuminate\Support\Collection;

$range = Range::from(1, 5);
$users = $range->map(fn($id) => User::find($id))->toCollection();

// Filter even IDs
$evens = $range->filter(fn($id) => $id % 2 === 0)->toArray();

4. Query Builder Integration

Add a whereInRange method to Eloquent queries:

// In a Model or Query Builder extension
public function scopeWhereInRange($query, string $column, int $start, int $end, int $step = 1)
{
    return $query->whereIn($column, Range::from($start, $end, $step)->toArray());
}

// Usage
User::whereInRange('id', 100, 200, 2)->get();

5. Batch Processing with Queues

Dispatch lazy ranges to queue workers:

// Job class
public function handle()
{
    $range = Range::from(1, 1_000_000)->lazy();

    foreach ($range as $id) {
        ProcessUserJob::dispatch($id);
    }
}

6. Validation

Use ranges for type-safe validation (e.g., age constraints):

use PHPStandardLibrary\Range\Range;

function validateAge(int $age): void
{
    $validAges = Range::from(18, 65);
    if (!$validAges->contains($age)) {
        throw new \InvalidArgumentException("Age must be between 18 and 65.");
    }
}

7. Dynamic API Endpoints

Parse range strings from request parameters:

// Route: /users?ids=100-200:2
$rangeStr = request('ids'); // "100-200:2"
$range = Range::fromString($rangeStr); // Range(100, 200, 2)

$users = User::whereIn('id', $range->toArray())->get();

Laravel-Specific Patterns

1. Service Provider Setup

Register a Range facade for cleaner syntax:

// app/Providers/AppServiceProvider.php
use PHPStandardLibrary\Range\Range;
use Illuminate\Support\Facades\Facade;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Facade::alias(Range::class, 'Range');
    }
}

2. Collection Macros

Extend Laravel Collections with range methods:

// app/Providers/AppServiceProvider.php
use Illuminate\Support\Collection;

Collection::macro('range', function ($start, $end, $step = 1) {
    return $this->merge(Range::from($start, $end, $step)->toArray());
});

// Usage
$ids = collect([1, 2, 3])->range(4, 6); // [1, 2, 3, 4, 5, 6]

3. Testing with Factories

Generate test data using ranges:

// tests/Feature/UserTest.php
public function test_bulk_operations()
{
    $range = Range::from(1, 100);
    $users = $range->map(fn($id) => User::factory()->create(['id' => $id]));

    $this->assertCount(100, $users);
}

4. Pagination with Ranges

Replace paginate() with custom range-based pagination:

// Controller
public function index(Request $request)
{
    $page = $request->query('page', 1);
    $perPage = $request->query('per_page', 20);

    $start = ($page - 1) * $perPage + 1;
    $end = $page * $perPage;

    $range = Range::from($start, $end);
    $users = User::whereIn('id', $range->toArray())->get();

    return response()->json($users);
}

Gotchas and Tips

Pitfalls

1. Off-by-One Errors

  • Issue: Range::from(1, 1) includes only 1 (inclusive by default). Use toArray() to verify:
    $range = Range::from(1, 1);
    var_dump($range->toArray()); // [1]
    
  • Fix: Explicitly set inclusive flag:
    $range = Range::from(1, 1, 1, false); // Empty range
    

2. Lazy Range Memory Leaks

  • Issue: Unclosed lazy iterators can cause memory leaks in long-running processes (e.g., CLI scripts).
  • Fix: Always consume lazy ranges fully or explicitly close them:
    $lazy = Range::from(1, 1_000_000)->lazy();
    foreach ($lazy as $item) {
        // Process item
    }
    // OR
    $lazy->close(); // Explicitly close if not fully consumed
    

3. Negative Steps

  • Issue: Range::from(10, 1, -1) creates an infinite loop if not handled.
  • Fix: Validate steps or use assertValid():
    $range = Range::from(10, 1, -1);
    $range->assertValid(); // Throws RangeException if invalid
    

4. Floating-Point Ranges

  • Issue: The package only supports integers. Passing floats throws RangeException.
  • Fix: Use intval() or a separate library for decimal ranges:
    $range = Range::from(intval(1.5), intval(3.2)); // [2, 3]
    

5. Serialization Issues

  • Issue: Range objects may not serialize/deserialize cleanly (e.g., for caching).
  • Fix: Convert to arrays before caching:
    cache()->put('range', Range::from(1, 10)->toArray());
    

6. Performance Overhead

  • Issue: Range objects have a ~5% overhead vs. native loops for small ranges.
  • Fix: Benchmark and use native loops for performance-critical code:
    // For tiny ranges (e.g., <100 items), native loops may be faster:
    for ($i = 1; $i <= 10; $i++) { ... }
    

Debugging Tips

1. Inspect Range Objects

Add a debug method to your RangeHelper facade:

// app/Helpers/RangeHelper.php
public static function debug(Range $range)
{
    \Log::debug('Range:', [
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.
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast