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

Utils Laravel Package

digitalrevolution/utils

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   ```bash
   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;
  1. 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
    
  2. Where to Look First:

    • Arrays: For collection manipulation (e.g., flatten, groupBy, fetchByPath).
    • 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.

  • 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());
        });
    }
    
  • 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'));
      
  • 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 in phpstan.neon:
      includes:
        -
      
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky