lemmon/validator

A lightweight, fluent validation library for PHP.

Installs: 28

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/lemmon/validator

v0.5.0 2025-10-08 05:39 UTC

This package is auto-updated.

Last update: 2025-10-08 05:41:26 UTC


README

CI Latest Stable Version License

A comprehensive, fluent validation library for PHP, inspired by Valibot and Zod. Build type-safe, readable validation schemas with chainable methods and intelligent error handling.

โœจ Features

  • ๐Ÿ”’ Type-safe validation for strings, integers, floats, arrays, and objects
  • ๐Ÿ”— Fluent, chainable API for readable and maintainable validation rules
  • ๐Ÿ“‹ Comprehensive error collection with detailed, structured feedback
  • โš™๏ธ Custom validation functions with context-aware parameters
  • ๐Ÿงฉ Logical combinators (Validator::allOf(), Validator::anyOf(), Validator::not()) for complex validation logic
  • ๐Ÿ”„ Smart type coercion with configurable behavior
  • ๐ŸŽฏ Schema validation for nested data structures
  • โšก Universal transformations (transform(), pipe()) for post-validation data processing

๐Ÿš€ Quick Start

use Lemmon\Validator;

// Simple validation
$email = Validator::isString()
    ->email()
    ->validate('user@example.com');

// Schema validation
$userSchema = Validator::isAssociative([
    'name' => Validator::isString()->required(),
    'age' => Validator::isInt()->min(18),
    'email' => Validator::isString()->email(),
    'preferences' => Validator::isObject([
        'theme' => Validator::isString()->oneOf(['light', 'dark'])->default('light'),
        'notifications' => Validator::isBool()->default(true)
    ])
]);

[$valid, $user, $errors] = $userSchema->tryValidate($input);

๐Ÿ“š Documentation

Getting Started

Validation Guides

API Reference

Examples

๐Ÿ“ฆ Installation

composer require lemmon/validator

Requirements: PHP 8.1 or higher

๐Ÿƒโ€โ™‚๏ธ Quick Examples

String Validation with Formats

// Email validation
$email = Validator::isString()->email()->validate('user@example.com');

// URL with custom message
$url = Validator::isString()
    ->url('Please provide a valid URL')
    ->validate('https://example.com');

// Pattern matching
$code = Validator::isString()
    ->pattern('/^[A-Z]{2}\d{4}$/', 'Code must be 2 letters + 4 digits')
    ->validate('AB1234');

Numeric Validation

// Integer with constraints
$age = Validator::isInt()
    ->min(18)
    ->max(120)
    ->validate(25);

// Enhanced coercion for form data
$quantity = Validator::isInt()
    ->coerce() // Empty strings become 0
    ->validate(''); // Returns: 0

// Float with precision
$price = Validator::isFloat()
    ->positive()
    ->multipleOf(0.01) // Cents precision
    ->coerce() // Empty strings become 0.0
    ->validate(19.99);

Array Validation

// Array filtering with auto-reindexing
$tags = Validator::isArray()
    ->filterEmpty() // Removes '', null but keeps 0, false, []
    ->validate(['php', '', 'javascript', null, 'react']);
// Returns: ['php', 'javascript', 'react'] (properly indexed)

// With item validation
$numbers = Validator::isArray()
    ->items(Validator::isInt()->positive())
    ->filterEmpty()
    ->validate([1, '', 2, null, 3]);
// Returns: [1, 2, 3]

Data Transformations

// Type-preserving transformations with pipe()
$name = Validator::isString()
    ->pipe('trim', 'strtoupper') // Maintains string type
    ->validate('  john doe  '); // Returns: "JOHN DOE"

// Type-changing transformations with transform()
$count = Validator::isString()
    ->transform(fn($v) => explode(',', $v)) // String โ†’ Array
    ->pipe('array_unique')                  // Array operations (auto-reindexed)
    ->transform('count')                    // Array โ†’ Int
    ->validate('a,b,a,c'); // Returns: 3

// Complex multi-type chains
$result = Validator::isArray()
    ->pipe('array_unique', 'array_reverse') // Array operations
    ->transform(fn($v) => implode(',', $v)) // Array โ†’ String
    ->pipe('trim', 'strtoupper')            // String operations
    ->transform('strlen')                   // String โ†’ Int
    ->validate(['a', 'b', 'a']); // Returns: 3

Custom Validation

// Context-aware validation
$passwordConfirm = Validator::isString()->addValidation(
    function ($value, $key, $input) {
        return isset($input['password']) && $value === $input['password'];
    },
    'Password confirmation must match password'
);

Advanced Logic

// Logical combinators
$flexibleId = Validator::anyOf([
    Validator::isInt()->positive(),
    Validator::isString()->uuid()
]);

$strictUser = Validator::allOf([
    Validator::isAssociative(['name' => Validator::isString()]),
    Validator::isAssociative(['email' => Validator::isString()->email()])
]);

$notBanned = Validator::not(
    Validator::isString()->oneOf(['banned', 'suspended']),
    'User cannot be banned or suspended'
);

๐Ÿค Contributing

We welcome contributions! Please see our Contributing Guide for details.

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ”— Links