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

Utils Laravel Package

digitalrevolution/utils

A PHP 8.3+ utility library of everyday helper classes, focused on array operations such as first/last, find, flatten, map, groupBy, diff, unique, remove, JSON conversion, and path fetching, plus iterable and string helpers.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require digitalrevolution/utils
    

    Add the namespace to your composer.json autoload or use it directly via use statements:

    use DigitalRevolution\Utils\Arrays;
    use DigitalRevolution\Utils\Assert;
    use DigitalRevolution\Utils\Stringify;
    use DigitalRevolution\Utils\Closures;
    
  2. First Use Case: Replace native array operations with safer, more expressive methods. For example, replace reset($array) with:

    $firstItem = Arrays::first($array); // Throws exception if empty
    $firstItemOrNull = Arrays::firstOrNull($array); // Returns null if empty
    

    Need to normalize a list of IDs coming from a request or query string? Use the new toIntList:

    $ids = Arrays::toIntList($request->input('ids', [])); // [1, 2, 3]
    
  3. Where to Look First:

    • Arrays: For collection manipulation (e.g., flatten, groupBy, fetchByPath, toIntList).
    • Assert: For fluent validation (e.g., Assert::notNull($value)->isInstanceOf(MyClass::class)).
    • Stringify: For debugging or logging (e.g., Stringify::value($complexObject)).
    • Closures: For lazy initialization (e.g., Closures::unfold($closure)).

Implementation Patterns

1. Array Manipulation Workflows

  • Flattening Nested Arrays:

    $flatArray = Arrays::flatten($nestedArray);
    

    Useful for API responses or nested configurations.

  • Path-Based Access:

    $value = Arrays::fetchByPath($array, ['user', 'profile', 'name']);
    Arrays::assignByPath($array, ['user', 'profile', 'age'], 30);
    

    Ideal for deeply nested Laravel config or request data.

  • Grouping and Mapping:

    $grouped = Arrays::groupBy($users, fn($user) => $user['department']);
    $mapped = Arrays::map($users, fn($user, $key) => strtoupper($user['name']));
    

    Replace collect()->groupBy() or array_map() for type safety.

  • Casting to an Integer List (v1.34.0+):

    $ids = Arrays::toIntList($request->input('ids', []));
    $ids = Arrays::toIntList(explode(',', $request->query('ids', '')));
    

    Ideal for normalizing query-string values, CSV imports, or form multi-selects into a consistent list<int> before passing them into whereIn(), repositories, or DTOs. Replaces array_map('intval', $values) boilerplate with a typed, single-purpose helper.

  • Safe Removal:

    $filtered = Arrays::remove($items, fn($item) => $item->isArchived());
    $filtered = Arrays::removeTypes($items, [null, 'string']);
    

    Cleaner than manual array_filter with custom logic.


2. Assertion-Driven Validation

  • Fluent Chaining:

    Assert::notNull($user)->isInstanceOf(User::class)->notFalse();
    

    Replace if (!$user) throw new \RuntimeException(...) with self-documenting code.

  • Custom Error Messages:

    Assert::greaterThan($age, 18, 'User must be at least 18 years old');
    

    Useful in Laravel form requests or API validation.

  • Type-Specific Assertions:

    Assert::isArray($config)->nonEmptyArray();
    Assert::fileExists($path)->readable();
    

    Validate Laravel config, file uploads, or environment variables.


3. Stringify for Debugging

  • Logging Complex Data:

    \Log::debug('User data:', ['data' => Stringify::value($user)]);
    

    Replace var_export or json_encode for human-readable output.

  • Template Rendering:

    $template = "User: {user}, Status: {status}";
    $rendered = str_replace(
        ['{user}', '{status}'],
        [Stringify::value($user), Stringify::value($user->status)]
    );
    

4. Closures for Lazy Loading

  • Service Initialization:

    $service = fn() => new ExpensiveService();
    $instance = Closures::unfold($service); // Executes once
    

    Useful for Laravel service providers or dependency injection.

  • Memoization:

    $cache = [];
    $getCached = fn($key) => $cache[$key] ?? ($cache[$key] = fetchExpensiveData($key));
    $value = Closures::unfold($getCached('key'));
    

5. Integration with Laravel

  • Form Request Validation:

    public function rules(): array {
        return [
            'age' => ['integer', 'min:18'],
            // Custom validation via Assert:
            'user' => ['required', 'array', 'min:1'],
        ];
    }
    
    public function withValidator($validator) {
        $validator->after(function ($validator) {
            Assert::notNull($this->user['id']);
            Assert::greaterThan($this->user['age'], 0);
        });
    }
    
  • Service Providers:

    public function register() {
        $this->app->singleton(ExpensiveService::class, function () {
            return Closures::unfold(fn() => new ExpensiveService());
        });
    }
    
  • Normalizing Request Input for Queries:

    $ids = Arrays::toIntList($request->input('ids', []));
    $users = User::whereIn('id', $ids)->get();
    
  • API Responses:

    return response()->json([
        'data' => Arrays::map($users, fn($user) => [
            'id' => $user['id'],
            'name' => Stringify::value($user['name']),
        ]),
    ]);
    

Gotchas and Tips

Arrays

  • first/last vs firstOrNull/lastOrNull: Always prefer *OrNull in Laravel controllers to avoid UndefinedArrayKeyException in views/blades.

    $firstItem = Arrays::firstOrNull($array); // Safe for Blade
    
  • fetchByPath and assignByPath:

    • Throws \InvalidArgumentException if path is invalid.
    • Use Arrays::wrap($path) if path might be a scalar:
      Arrays::fetchByPath($array, Arrays::wrap('user.profile'));
      
  • toIntList (new in v1.34.0):

    • Expects an array of scalar values (strings, numerics) — pass explode(',', ...) or $request->input(...) directly.
    • Be aware of the usual PHP integer-casting edge cases for non-numeric strings; validate upstream with Assert or a Form Request rule if input is untrusted (e.g. ['integer'] on ids.*).
    • The result is a list (sequential integer keys). Wrap your source with array_values() if you need to be certain, though the helper is intended to normalize this for you.
    • Great paired with Assert::isList(...) for asserting the shape you feed into whereIn() or repository methods.
  • remove Performance:

    • For large arrays, Arrays::removeNull() is optimized (uses array_filter internally).
    • For custom callbacks, consider array_filter + array_values if order matters.
  • equals vs ==:

    • Arrays::equals($a, $b) ignores order and supports ComparableInterface.
    • Useful for testing or comparing Laravel config arrays.

Assert

  • Exception Messages:

    • Custom messages override default ones:
      Assert::notNull($value, 'Custom error message');
      
    • Use regex in messages for multi-part assertions (e.g., Assert::greaterThan($age, 18, 'Age must be > {0}')).
  • isList vs isArray:

    • isList checks for sequential arrays (no gaps in keys).
    • Useful for Laravel collections or API payloads:
      Assert::isList($response['data']);
      
  • File Assertions:

    • fileExists and readable/writable are Laravel-friendly for storage paths:
      Assert::fileExists(storage_path('app/logs/error.log'))->readable();
      
  • Nested Assertions:

    • Messages for nested assertions (e.g., Assert::notNull($user)->isInstanceOf(User::class)) require explicit message passing:
      Assert::notNull($user, 'User not found')->isInstanceOf(User::class, 'Invalid user type');
      

Stringify

  • Edge Cases:

    • Stringify::value(null) returns 'null'.
    • Stringify::value([]) returns 'empty-array'.
    • Stringify::value(new DateTime()) returns '2023-10-01T00:00:00+00:00'.
    • For JsonSerializable, uses json_encode($value, JSON_THROW_ON_ERROR).
  • Debugging:

    • Use in Laravel app/Exceptions/Handler.php for exception debugging:
      report(new \RuntimeException(Stringify::value($context)));
      

Closures

  • unfold Behavior:
    • Executes the closure only once, even if called multiple times.
    • Useful for Laravel service containers or singleton services:
      $service = fn() => new DatabaseConnection();
      $connection = Closures::unfold($service); // Executes once
      
    • Gotcha: Reassigning the closure variable resets the unfolded value:
      $service = fn() => new Service();
      $instance1 = Closures::unfold($service); // Executes
      $service = fn() => new AnotherService(); // Resets!
      $instance2 = Closures::unfold($service); // Executes again
      

General Tips

  • PHPStan/Laravel IDE Helper:
    • The package includes PHPStan extensions for Assert methods. Enable them in phpstan.neon by including the package's extension:
      includes:
        - vendor/digitalrevolution/utils/phpstan-extension.neon
      
  • Dev tooling only changes: v1.34.0 bumps phpmd/phpmd to v3. This is a dev dependency used by the package itself for its own code quality checks. It has no runtime impact on your application and requires no action on your side.
  • Upgrading: v1.34.0 is additive — no breaking changes. A composer update digitalrevolution/utils is enough; you can start using Arrays::toIntList immediately.
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
adachsoft/php-code-style