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

atournayre/assert

View on GitHub
Deep Wiki
Context7

Getting Started

Install via Composer:

composer require atournayre/assert

First Use Case: Validate an array of objects in a Laravel service method.

use Atournayre\Assert\Assert;

// In a service method
public function processUsers(array $users): void
{
    Assert::isListOf($users, User::class, 'Users must be an array of User objects');
    // Proceed with business logic
}

Where to Look First:

  • README.md for assertion methods.
  • webmozart/assert for base functionality.
  • Test files for edge cases (e.g., Bank, Coordinates validations).

Implementation Patterns

1. Input Validation in Services

Pattern: Validate method arguments before processing.

public function createOrder(array $items, string $currency): Order
{
    Assert::isListOf($items, Product::class, 'Order items must be Products');
    Assert::isType($currency, 'string', 'Currency must be a string');
    // ...
}

2. Domain-Specific Validations

Pattern: Use niche assertions for specialized data.

public function validateBankTransfer(string $iban, string $bic): void
{
    Assert::isBankAccount($iban, 'Invalid IBAN');
    Assert::isBankIdentifier($bic, 'Invalid BIC');
}

3. API Request Validation

Pattern: Combine with Laravel middleware for HTTP validation.

// app/Http/Middleware/ValidateRequest.php
public function handle($request, Closure $next)
{
    $data = $request->json()->all();
    Assert::isMapOf($data, 'string', 'Request body must be key-value pairs');
    return $next($request);
}

4. Data Transfer Objects (DTOs)

Pattern: Validate DTOs before processing.

public function updateProfile(ProfileDto $dto): void
{
    Assert::allIsType($dto->coordinates, 'array', 'Coordinates must be an array');
    Assert::isCoordinates($dto->coordinates, 'Invalid coordinates');
}

5. Error Handling Integration

Pattern: Convert assertions to Laravel ValidationException.

use Illuminate\Validation\ValidationException;

try {
    $this->validateRequest($request);
} catch (InvalidArgumentException $e) {
    throw ValidationException::withMessages(['error' => [$e->getMessage()]]);
}

6. Testing Workflows

Pattern: Use assertions in unit tests for preconditions.

public function testCreateOrder()
{
    $this->expectException(InvalidArgumentException::class);
    $this->service->createOrder([1, 'invalid'], 'USD');
}

Gotchas and Tips

Pitfalls

  1. Performance Overhead:

    • Assertions validate every call (e.g., isListOf iterates the array). Avoid in tight loops or high-throughput APIs.
    • Tip: Cache results if assertions are called repeatedly with the same data.
  2. Error Message Customization:

    • Default messages may not match Laravel’s validation format. Override them explicitly:
      Assert::isType($value, 'string', 'The :attribute must be a string.');
      
  3. Type Hints vs. Assertions:

    • PHP 7.4+ type hints (e.g., public function process(array $users)) are not replaced by assertions. Use both for robustness:
      public function process(array $users) // Type hint
      {
          Assert::isListOf($users, User::class); // Runtime check
      }
      
  4. Niche Assertion Limitations:

    • isBankAccount, isCoordinates, etc., may not cover all edge cases. Test thoroughly with:
      Assert::isBankAccount('GB82WEST12345698765432', 'Invalid IBAN format');
      
  5. Dependency on webmozart/assert:

    • If webmozart/assert breaks changes, this package may fail. Pin versions in composer.json:
      "require": {
          "webmozart/assert": "^1.11"
      }
      

Debugging Tips

  1. Enable Error Details:

    • Laravel’s APP_DEBUG=true will show full assertion error messages in development.
  2. Log Assertion Failures:

    • Wrap assertions in a logger for production debugging:
      try {
          Assert::isListOf($data, User::class);
      } catch (InvalidArgumentException $e) {
          \Log::error($e->getMessage(), ['data' => $data]);
          throw $e;
      }
      
  3. Test Edge Cases:

    • Validate with:
      • Empty arrays ([]).
      • Mixed types ([1, 'string']).
      • null or false values.

Extension Points

  1. Add Custom Assertions:

    • Extend the Assert class:
      namespace App\Services;
      
      use Atournayre\Assert\Assert as BaseAssert;
      
      class CustomAssert extends BaseAssert
      {
          public static function isValidPaymentMethod(string $method): void
          {
              $validMethods = ['credit_card', 'paypal', 'bank_transfer'];
              if (!in_array($method, $validMethods)) {
                  throw new \InvalidArgumentException("Invalid payment method: {$method}");
              }
          }
      }
      
  2. Override Error Messages:

    • Use Laravel’s trans() for localized messages:
      Assert::isType($value, 'string', trans('validation.string', ['attribute' => 'name']));
      
  3. Integrate with Laravel Validation:

    • Create a custom validation rule:
      use Atournayre\Assert\Assert;
      use Illuminate\Contracts\Validation\Rule;
      
      class IsListOf implements Rule
      {
          public function __construct(private string $type) {}
      
          public function passes($attribute, $value): bool
          {
              try {
                  Assert::isListOf($value, $this->type);
                  return true;
              } catch (\InvalidArgumentException) {
                  return false;
              }
          }
      
          public function message(): string
          {
              return 'The :attribute must be a list of '.class_basename($this->type).'.';
          }
      }
      
      Usage:
      $request->validate([
          'users' => ['required', new IsListOf(User::class)],
      ]);
      

Configuration Quirks

  1. No Laravel Config:

    • The package has no config file. All assertions are stateless and work out-of-the-box.
  2. Autoloading:

    • Ensure composer dump-autoload is run after installation if assertions fail to load.
  3. PHP Version:

    • Requires PHP 8.0+. Test with php -v before using in older environments.

Pro Tips

  1. Combine with Laravel’s Validator:

    • Use atournayre/assert for domain logic and Laravel’s Validator for HTTP input:
      // HTTP request validation (Laravel)
      $request->validate(['email' => 'required|email']);
      
      // Domain validation (Assert)
      Assert::isEmail($user->email); // Custom domain-specific check
      
  2. Use in Form Requests:

    • Validate DTOs or complex objects in FormRequest classes:
      public function rules(): array
      {
          return [
              'data' => ['required', function ($attribute, $value, $fail) {
                  try {
                      Assert::isMapOf($value, 'string', $fail);
                  } catch (\InvalidArgumentException $e) {
                      $fail($e->getMessage());
                  }
              }],
          ];
      }
      
  3. Document Assertions:

    • Add PHPDoc comments to methods using assertions:
      /**
       * @param array<User> $users List of User objects
       * @throws \InvalidArgumentException If $users is not a list of Users
       */
      public function processUsers(array $users): void
      {
          Assert::isListOf($users, User::class);
          // ...
      }
      
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
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