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

Assert Laravel Package

webmozart/assert

Lightweight PHP assertion library for validating method input/output. Provides fast, readable checks via Webmozart\Assert\Assert with consistent error-message placeholders, throwing InvalidArgumentException on failure. Ideal for safer, less repetitive validation code.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require webmozart/assert
    

    No additional configuration is required—just import the Assert class.

  2. First Use Case: Validate constructor parameters or method inputs in a Laravel service/class:

    use Webmozart\Assert\Assert;
    
    class UserService {
        public function __construct(private string $apiKey) {
            Assert::stringNotEmpty($this->apiKey, 'API key must be a non-empty string');
        }
    }
    
  3. Where to Look First:

    • Assertion List: README.md#assertions for available methods.
    • Placeholder Format: %s (value), %2$s (additional params) for custom error messages.
    • Type-Specific Methods: Prefer stringNotEmpty() over string() + empty() checks.

Implementation Patterns

1. Constructor Validation

Pattern: Validate all constructor dependencies upfront.

class OrderProcessor {
    public function __construct(
        private string $orderId,
        private array $items,
        private ?int $discount = null
    ) {
        Assert::uuid($orderId, 'Order ID must be a valid UUID');
        Assert::isNonEmptyList($items, 'Order must have items');
        Assert::greaterThanEq($discount ?? 0, 0, 'Discount cannot be negative');
    }
}

2. Method Input Validation

Pattern: Use assertions in setter methods or public APIs.

class UserRepository {
    public function updateEmail(string $userId, string $email): void {
        Assert::uuid($userId, 'Invalid user ID');
        Assert::email($email, 'Invalid email format');
        // Proceed with DB update...
    }
}

3. Custom Error Messages

Pattern: Reuse base messages with placeholders for consistency.

// Reusable message for type checks
const MESSAGE_INVALID_TYPE = 'Expected %s, got %s';

Assert::string($value, sprintf(MESSAGE_INVALID_TYPE, 'string', gettype($value)));

4. Integration with Laravel

Pattern: Combine with Laravel’s validation or form requests.

// In a Form Request
public function rules(): array {
    return ['email' => 'required|email'];
}

public function withValidator($validator) {
    $validator->after(function ($validator) {
        Assert::email($this->email, 'Custom error: Invalid email');
    });
}

5. Domain-Specific Assertions

Pattern: Extend assertions for business logic (e.g., Assert::validStatus()).

class OrderAssertions {
    public static function validStatus(string $status): void {
        Assert::oneOf($status, ['pending', 'shipped', 'cancelled'],
            'Invalid order status: %s');
    }
}

6. Testing

Pattern: Use assertions in unit tests to validate outputs.

public function testCalculateDiscount() {
    $discount = $this->service->calculateDiscount(100, 0.2);
    Assert::greaterThan($discount, 0, 'Discount must be positive');
    Assert::lessThan($discount, 100, 'Discount cannot exceed total');
}

Gotchas and Tips

Pitfalls

  1. Performance Overhead:

    • Assertions add minimal overhead but can slow down hot paths. Use sparingly in loops or high-frequency methods.
    • Tip: Cache repeated assertions (e.g., classExists() for static checks).
  2. Placeholder Order:

    • %s is always the tested value. Additional placeholders (e.g., %2$s for ranges) vary by method.
    • Gotcha: Incorrect placeholder order in custom messages breaks error clarity.
      // Wrong: %2$s appears before %s
      Assert::range($age, 18, 65, 'Age must be between %2$s and %s');
      
  3. Type Casting:

    • integerish() casts strings like "123" to integers but fails for "abc".
    • Tip: Use integer() if you need strict integer types.
  4. Resource Assertions:

    • resource() checks require PHP’s is_resource() (deprecated in PHP 8.1+).
    • Tip: Avoid in new code; use GuzzleHttp\Psr7\StreamInterface or similar for HTTP resources.
  5. Laravel-Specific:

    • Gotcha: Assertions don’t integrate with Laravel’s validation pipeline. Use them for:
      • Early returns in controllers.
      • Service layer validation.
      • Custom logic not covered by Laravel’s validators.

Debugging Tips

  1. Custom Exceptions:

    • Catch Webmozart\Assert\InvalidArgumentException for graceful handling:
      try {
          Assert::email($email);
      } catch (InvalidArgumentException $e) {
          return back()->withErrors(['email' => $e->getMessage()]);
      }
      
  2. Assertion Chaining:

    • Combine assertions for complex rules:
      Assert::all(
          [$id, $name, $email],
          fn ($value) => Assert::notEmpty($value, 'Field cannot be empty')
      );
      
  3. Dynamic Messages:

    • Use sprintf for dynamic values in messages:
      Assert::minLength($password, 8,
          'Password must be at least %d characters (got %s)');
      
  4. Testing Edge Cases:

    • Test assertions with:
      • null, empty strings, false, 0.
      • Unicode strings (e.g., Assert::unicodeLetters()).
      • Boundary values (e.g., Assert::range($value, 0, 1) with $value = 0 or 1).

Extension Points

  1. Custom Assertions:

    • Extend the Assert class or create static methods:
      class AppAssert extends Assert {
          public static function validPhone(string $phone): void {
              Assert::regex($phone, '/^\+?[0-9]{10,15}$/', 'Invalid phone format');
          }
      }
      
  2. Integration with Laravel:

    • Service Providers: Bind custom assertions to the container.
    • Macros: Add Laravel-specific assertions (e.g., for Eloquent models):
      Assert::macro('validModelId', function ($id, $modelClass) {
          Assert::uuid($id);
          Assert::notNull($modelClass::find($id), 'Model not found');
      });
      
  3. Performance Optimization:

    • For frequent checks, use Assert::that() with a closure:
      Assert::that($user->role, fn ($role) =>
          Assert::oneOf($role, ['admin', 'editor', 'user'])
      );
      
  4. Localization:

    • Translate error messages using Laravel’s trans() helper:
      Assert::string($name, trans('validation.string', ['attribute' => 'name']));
      
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.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai