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

beberlei/assert

Lightweight assertion library for validating method arguments and input data in PHP. Provides a fluent, readable API with many built-in rules (string, numeric, email, UUID, collection, etc.), clear exceptions, and easy extensibility for custom constraints.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require beberlei/assert
    

    Add to composer.json under require-dev if only for testing.

  2. First Use Case: Validate a user input in a Laravel controller or service:

    use Assert\Assertion;
    
    public function store(Request $request)
    {
        $name = $request->input('name');
        Assertion::notEmpty($name, 'Name cannot be empty');
        Assertion::string($name, 'Name must be a string');
        // Proceed with logic...
    }
    
  3. Where to Look First:


Implementation Patterns

1. Validation in Business Logic

Replace repetitive if checks with assertions in models/services:

// In UserService.php
public function createUser(array $data)
{
    Assertion::keyExists($data, 'email');
    Assertion::email($data['email']);
    Assert::that($data['age'])->integer()->greaterThan(18);
    // Create user...
}

2. Fluent API for Readability

Use Assert::that() for multi-condition validation:

// In RequestValidator.php
public function validateRequest(array $request)
{
    Assert::that($request['price'])->greaterThan(0)->numeric();
    Assert::that($request['name'])->notEmpty()->string()->maxLength(100);
}

3. Lazy Assertions for Forms

Collect all validation errors before responding:

// In FormHandler.php
public function handleForm(array $data)
{
    $errors = [];
    Assert::lazy()
        ->that($data['email'], 'email')->email()
        ->that($data['password'], 'password')->minLength(8)
        ->that($data['age'], 'age')->integer()->between(18, 120)
        ->verifyNow($errors); // $errors now contains all failures

    if (!empty($errors)) {
        return response()->json(['errors' => $errors], 422);
    }
    // Process data...
}

4. Null/All Helpers

Validate optional or array values concisely:

// In DataSanitizer.php
public function sanitize(array $data)
{
    Assertion::nullOrString($data['optional_field']);
    Assertion::allIsInstanceOf($data['tags'], 'string');
}

5. Integration with Laravel Validation

Use assertions in FormRequest validation rules:

// In CreatePostRequest.php
public function rules()
{
    return [
        'title' => ['required', 'string', function ($attribute, $value, $fail) {
            Assertion::maxLength($value, 255) or $fail('Title too long.');
        }],
    ];
}

6. Custom Assertions

Extend for domain-specific rules:

// In CustomAssertions.php
use Assert\Assertion;

class CustomAssertions extends Assertion
{
    public static function validSlug(string $slug)
    {
        self::string($slug);
        self::regex($slug, '/^[a-z0-9\-]+$/i');
    }
}

// Usage:
CustomAssertions::validSlug($request->slug);

Gotchas and Tips

Pitfalls

  1. Exception Handling:

    • Assertions throw AssertionFailedException by default. Ensure you catch and handle them gracefully in APIs:
      try {
          Assertion::email($email);
      } catch (AssertionFailedException $e) {
          return response()->json(['error' => $e->getMessage()], 400);
      }
      
  2. Lazy Assertions:

    • verifyNow() must be called to trigger exceptions. Forgetting this will silently collect errors.
    • Property paths in that($value, 'path') must match your error reporting (e.g., for API responses).
  3. Performance:

    • Avoid overusing assertions in tight loops (e.g., batch processing). Use satisfy() for custom callbacks:
      Assertion::satisfy($items, fn($item) => is_array($item));
      
  4. Type Safety:

    • Assertions are strict. For example, integer() rejects float values even if they are whole numbers. Use integerish() if needed.
  5. Custom Exceptions:

    • Overriding the base Assertion class requires reimplementing all static methods. Prefer dependency injection for exceptions:
      // In AssertionServiceProvider.php
      $this->app->bind(Assertion::class, function () {
          return new CustomAssertion(new CustomExceptionHandler());
      });
      

Debugging Tips

  1. Inspect Failed Assertions:

    • Use $e->getConstraints() to debug complex assertions (e.g., between()):
      catch (AssertionFailedException $e) {
          dd($e->getValue(), $e->getConstraints());
      }
      
  2. Lazy Assertion Errors:

    • Call getErrorExceptions() to inspect all failures before verifyNow():
      $lazy = Assert::lazy()->that($data['field'], 'field')->email();
      if ($lazy->hasErrors()) {
          dd($lazy->getErrorExceptions());
      }
      
  3. Custom Stringification:

    • Override stringify() in a custom Assertion class to improve error messages for your domain types:
      protected static function stringify($value)
      {
          if ($value instanceof YourModel) {
              return "YourModel[{$value->id}]";
          }
          return parent::stringify($value);
      }
      

Extension Points

  1. Custom Assertions:

    • Add new assertions by extending Assertion and using satisfy():
      public static function validPhone(string $phone)
      {
          self::satisfy($phone, fn($p) => preg_match('/^\+?[0-9\s\-\(\)]{10,}$/', $p));
      }
      
  2. Exception Customization:

    • Replace the default InvalidArgumentException with a custom exception class:
      class ValidationException extends \RuntimeException {}
      // Then bind it in your DI container.
      
  3. Integration with Laravel:

    • Create a macro for Assertion to add Laravel-specific helpers:
      // In AppServiceProvider.php
      Assertion::macro('activeUser', function ($user) {
          Assertion::notNull($user);
          Assertion::true($user->is_active);
      });
      // Usage: Assertion::activeUser(auth()->user());
      
  4. Testing:

    • Mock assertions in unit tests to verify validation logic:
      $this->expectException(AssertionFailedException::class);
      Assertion::email('invalid-email');
      

Config Quirks

  • No Configuration File: The package is zero-config. All behavior is controlled via method calls.
  • Locale/Translations: Unlike Symfony validators, this package does not support translations. Customize error messages via callbacks or override stringify().

Performance Considerations

  • Short-Circuiting: Assertions fail fast (throw exceptions immediately). For batch validation, use lazy().
  • Avoid in Loops: Assertions are not optimized for iterative checks. Use satisfy() with a custom callback for complex logic:
    Assertion::satisfy($items, fn($item) => $item->isValid());
    

Common Anti-Patterns

  1. Using Assertions for Input Filtering:

    • This package is for validation, not sanitization. Use Laravel’s Str::of() or Filter packages for cleaning input.
  2. Overusing satisfy():

    • Prefer built-in assertions (e.g., email()) over satisfy() for maintainability.
  3. Ignoring Lazy Assertions:

    • Always call verifyNow() or check hasErrors() to avoid silent failures.
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.
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
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata