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

Range Laravel Package

php-standard-library/range

Range types for PHP integer sequences with built-in iteration support. Use range objects to represent start/end bounds and step through values predictably. Part of PHP Standard Library; see docs, contribute, or report issues on GitHub.

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.
codraw/graphviz
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata