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:
Bank, Coordinates validations).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');
// ...
}
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');
}
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);
}
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');
}
Pattern: Convert assertions to Laravel ValidationException.
use Illuminate\Validation\ValidationException;
try {
$this->validateRequest($request);
} catch (InvalidArgumentException $e) {
throw ValidationException::withMessages(['error' => [$e->getMessage()]]);
}
Pattern: Use assertions in unit tests for preconditions.
public function testCreateOrder()
{
$this->expectException(InvalidArgumentException::class);
$this->service->createOrder([1, 'invalid'], 'USD');
}
Performance Overhead:
isListOf iterates the array). Avoid in tight loops or high-throughput APIs.Error Message Customization:
Assert::isType($value, 'string', 'The :attribute must be a string.');
Type Hints vs. Assertions:
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
}
Niche Assertion Limitations:
isBankAccount, isCoordinates, etc., may not cover all edge cases. Test thoroughly with:
Assert::isBankAccount('GB82WEST12345698765432', 'Invalid IBAN format');
Dependency on webmozart/assert:
webmozart/assert breaks changes, this package may fail. Pin versions in composer.json:
"require": {
"webmozart/assert": "^1.11"
}
Enable Error Details:
APP_DEBUG=true will show full assertion error messages in development.Log Assertion Failures:
try {
Assert::isListOf($data, User::class);
} catch (InvalidArgumentException $e) {
\Log::error($e->getMessage(), ['data' => $data]);
throw $e;
}
Test Edge Cases:
[]).[1, 'string']).null or false values.Add Custom Assertions:
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}");
}
}
}
Override Error Messages:
trans() for localized messages:
Assert::isType($value, 'string', trans('validation.string', ['attribute' => 'name']));
Integrate with Laravel Validation:
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)],
]);
No Laravel Config:
Autoloading:
composer dump-autoload is run after installation if assertions fail to load.PHP Version:
php -v before using in older environments.Combine with Laravel’s Validator:
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
Use in Form Requests:
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());
}
}],
];
}
Document 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);
// ...
}
How can I help you explore Laravel packages today?