PHPackages                             infocyph/reqshield - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. infocyph/reqshield

ActiveLibrary[HTTP &amp; Networking](/categories/http)

infocyph/reqshield
==================

Fast, modern PHP request validation and sanitization. Schema-based rules, fail-fast execution, typed input, PSR-7 friendly.

2.1(1mo ago)11.3k↓50%MITPHPPHP &gt;=8.4CI passing

Since Nov 5Pushed 1mo agoCompare

[ Source](https://github.com/infocyph/ReqShield)[ Packagist](https://packagist.org/packages/infocyph/reqshield)[ RSS](/packages/infocyph-reqshield/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (3)Dependencies (10)Versions (6)Used By (0)

🛡️ ReqShield
============

[](#️-reqshield)

[![Security & Standards](https://github.com/infocyph/ReqShield/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/infocyph/ReqShield/actions/workflows/build.yml)[![Packagist Downloads](https://camo.githubusercontent.com/0e5e0de4b91a2f93294bdac5facf5f24aa26597a0682e13ec20432fa5e36a37e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f696e666f637970682f526571536869656c643f636f6c6f723d677265656e266c696e6b3d68747470732533412532462532467061636b61676973742e6f72672532467061636b61676573253246696e666f63797068253246526571536869656c64)](https://camo.githubusercontent.com/0e5e0de4b91a2f93294bdac5facf5f24aa26597a0682e13ec20432fa5e36a37e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f696e666f637970682f526571536869656c643f636f6c6f723d677265656e266c696e6b3d68747470732533412532462532467061636b61676973742e6f72672532467061636b61676573253246696e666f63797068253246526571536869656c64)[![License: MIT](https://camo.githubusercontent.com/784362b26e4b3546254f1893e778ba64616e362bd6ac791991d2c9e880a3a64e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e2e737667)](https://opensource.org/licenses/MIT)[![Packagist Version](https://camo.githubusercontent.com/facdade87728b3b9b8145b752a851dda2244fec77e6b8fa048a13024298f3cee/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f696e666f637970682f526571536869656c64)](https://camo.githubusercontent.com/facdade87728b3b9b8145b752a851dda2244fec77e6b8fa048a13024298f3cee/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f696e666f637970682f526571536869656c64)[![Packagist PHP Version](https://camo.githubusercontent.com/966231733ca6ea981334306682aa84a78890a9ee3d9c0ca0fbe87692ff485991/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646570656e64656e63792d762f696e666f637970682f526571536869656c642f706870)](https://camo.githubusercontent.com/966231733ca6ea981334306682aa84a78890a9ee3d9c0ca0fbe87692ff485991/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646570656e64656e63792d762f696e666f637970682f526571536869656c642f706870)[![GitHub Code Size](https://camo.githubusercontent.com/03183113f7387fddf4b257769e43ab4711132b532d05616fa931221860fbf3ed/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c616e6775616765732f636f64652d73697a652f696e666f637970682f526571536869656c64)](https://camo.githubusercontent.com/03183113f7387fddf4b257769e43ab4711132b532d05616fa931221860fbf3ed/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c616e6775616765732f636f64652d73697a652f696e666f637970682f526571536869656c64)[![Documentation](https://camo.githubusercontent.com/57429d11ff64935405dd3bce0e4294c1786c99163b8134fc296683fe3693e402/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f646f63732d72656164746865646f63732d626c75652e737667)](https://docs.infocyph.com/projects/reqshield)

**Fast, modern PHP request validation and sanitization.** Schema-based rules, fail-fast execution, intelligent batching, and 103 built-in validation rules.

```
$validator = Validator::make([
    'email' => 'required|email|max:255',
    'age' => 'required|integer|min:18',
])->setSanitizers([
    'email' => ['trim', 'lowercase'],
])->setCasts([
    'age' => 'integer',
]);

$result = $validator->validate($data);

if ($result->passes()) {
    $clean = $result->typed();
    // ✅ All good!
}
```

---

✨ Features
----------

[](#-features)

- 🚀 **103 Built-in Rules** - Basic types, conditional rules, files, database checks, and more
- 🧹 **50+ Sanitizers** - Manual sanitization or built-in sanitize+validate pipeline
- ⚡ **Intelligent Batching** - Expensive DB checks are batched automatically
- 🎯 **Fail-Fast + Full Collection Modes** - Per-field fail-fast with configurable behavior
- 🔗 **Nested + Wildcard Validation** - Dot notation with wildcard expansion
- 🧾 **Custom Messages + Placeholders** - `:field`, `:rule`, `:min`, and more
- 🌍 **Locale Packs** - Per-rule localized message templates with fallback
- 🧠 **Failure Metadata** - Structured failures (`field`, `rule`, `message`, `value`)
- 📦 **Schema Fragments + Composition** - Reuse validation contracts across endpoints
- 🔁 **Conditional Closures** - `sometimes()` and `when()` for dynamic rule activation
- 🧱 **Schema Export** - JSON Schema, OpenAPI shape, and introspection metadata
- 🧰 **Typed Output + DTO Mapping** - Cast map + `toDTO()` support
- 📤 **Uploaded File Object Support** - Array-style uploads and PSR-7 style objects
- 🛠️ **PHP 8.4+** - Built with modern PHP features

---

📦 Installation
--------------

[](#-installation)

```
composer require infocyph/reqshield
```

**Requirements:** PHP 8.4+ and `ext-hash` with `xxh3` support

---

🚀 Quick Start
-------------

[](#-quick-start)

### Basic Validation

[](#basic-validation)

```
use Infocyph\ReqShield\Validator;

$validator = Validator::make([
    'email' => [
        'rules' => 'required|email|max:255',
        'sanitize' => ['trim', 'lowercase'],
        'alias' => 'Email Address',
    ],
    'password' => 'required|string|min:8|confirmed',
    'age' => 'required|integer|min:18',
])->setCasts([
    'age' => 'integer',
])->setCustomMessages([
    'email.required' => ':field is required.',
    '*.min' => ':field must be at least :min.',
]);

$result = $validator->validate($data);

if ($result->passes()) {
    $validated = $result->typed();
    // Process your data...
} else {
    $errors = $result->errors();
    $failures = $result->failures();
    // Handle validation errors...
}
```

### Sanitization

[](#sanitization)

Manual sanitization:

```
use Infocyph\ReqShield\Sanitizer;

$clean = [
    'email' => Sanitizer::email($input['email']),           // 'john@example.com'
    'username' => Sanitizer::alphaDash($input['username']), // 'john_doe'
    'age' => Sanitizer::integer($input['age']),             // 25
    'bio' => Sanitizer::string($input['bio']),              // Strips HTML tags
];

$result = $validator->validate($clean);
```

Or built-in sanitize+validate pipeline:

```
$validator = Validator::make([
    'email' => 'required|email',
    'contacts.*.email' => 'required|email',
])->setSanitizers([
    'email' => ['trim', 'lowercase'],
    'contacts.*.email' => ['trim', 'lowercase'],
]);
```

Or use the helper:

```
$clean = sanitize('  TEST@ex.com  ', 'email');           // 'TEST@ex.com'
$clean = sanitize('TEXT', ['string', 'lowercase']); // 'text'
```

---

📚 Available Rules (103)
-----------------------

[](#-available-rules-103)

ReqShield includes 103 validation rules covering several common scenarios:

- Basic Types
- Formats
- Strings
- Numbers
- Dates
- Conditionals
- Database
- Files
- Arrays
- Comparison
- Patterns
- Additional

**[📖 View Complete Rule Reference](https://docs.infocyph.com/projects/reqshield/en/latest/rule-reference.html)**

---

🧹 Available Sanitizers (50+)
----------------------------

[](#-available-sanitizers-50)

ReqShield includes 50+ sanitizers covering several common scenarios:

- Basic Types
- Case Conversions
- Text Processing
- Special Formats
- Alphanumeric Filters
- Security &amp; HTML
- Encoding
- Array Operations

**[📖 View Complete Sanitizer Reference](https://docs.infocyph.com/projects/reqshield/en/latest/sanitization.html)**

---

🎯 Advanced Features
-------------------

[](#-advanced-features)

### Nested Validation

[](#nested-validation)

Validate deeply nested arrays using dot notation:

```
$validator = Validator::make([
    'user.email' => 'required|email',
    'user.name' => 'required|min:3',
    'user.profile.age' => 'required|integer|min:18',
    'user.profile.bio' => 'string|max:500',
])->enableNestedValidation();

$data = [
    'user' => [
        'email' => 'john@example.com',
        'name' => 'John Doe',
        'profile' => [
            'age' => 25,
            'bio' => 'Software developer',
        ],
    ],
];

$result = $validator->validate($data);
```

Use `enableNestedValidation(false)` to flatten only required paths for large nested payloads.

### Custom Field Names

[](#custom-field-names)

Make error messages user-friendly:

```
$validator->setFieldAliases([
    'user_email' => 'Email Address',
    'contacts.*.email' => 'Contact Email',
]);
```

### Custom Messages + Locale Packs

[](#custom-messages--locale-packs)

```
$validator
    ->setCustomMessages([
        'email.required' => ':field is required.',
        '*.min' => ':field must be at least :min.',
        'contacts.*.email.email' => 'Each :field must be valid.',
    ])
    ->addLocalePack('es', [
        'required' => 'El campo :field es obligatorio.',
        '*' => 'El campo :field no es valido.',
    ])
    ->setLocale('es');
```

### Throw Exceptions on Failure

[](#throw-exceptions-on-failure)

```
use Infocyph\ReqShield\Exceptions\ValidationException;

$validator = Validator::make($rules)->throwOnFailure();

try {
    $result = $validator->validate($data);
    $validated = $result->validated();
} catch (ValidationException $e) {
    echo $e->getMessage();              // "Validation failed"
    print_r($e->getErrors());           // All errors
    echo $e->getErrorCount();           // Number of failed fields
    echo $e->getFirstFieldError('email'); // First error for specific field
    echo $e->getCode();                 // 422
}
```

### Failure Metadata for APIs

[](#failure-metadata-for-apis)

```
$result = $validator->validate($data);

if ($result->fails()) {
    return [
        'errors' => $result->errors(),
        'failures' => $result->failures(), // field, rule, message, value
    ];
}
```

### Conditional Rules

[](#conditional-rules)

```
$validator
    ->sometimes('vat', 'required', fn(array $data) => ($data['type'] ?? null) === 'business')
    ->when(
        fn(array $data) => ($data['country'] ?? null) === 'US',
        fn() => ['state' => 'required|string'],
    );
```

### Schema Fragments

[](#schema-fragments)

```
Validator::defineFragment('address', [
    'line1' => 'required|string|max:120',
    'zip' => 'required|digits:5',
]);

$validator = Validator::make([
    'name' => 'required|string',
])->useFragment('address', 'billing');
```

### Typed Output + DTO

[](#typed-output--dto)

```
$validator = Validator::make([
    'age' => 'required|integer',
    'active' => 'required|boolean',
])->setCasts([
    'age' => 'integer',
    'active' => 'boolean',
])->setDtoClass(App\DTO\UserInput::class);

$result = $validator->validate($data);
$typed = $result->typed();
$dto = $result->toDTO();
```

### Custom Rules (Simple)

[](#custom-rules-simple)

Use callbacks for quick custom validation:

```
use Infocyph\ReqShield\Rules\Callback;

$validator = Validator::make([
    'code' => [
        'required',
        new Callback(
            callback: fn($value, $field, $data) => $value % 2 === 0,
            message: 'The code must be an even number'
        ),
    ],
]);
```

### Custom Rules (Advanced)

[](#custom-rules-advanced)

Create reusable rule classes:

```
use Infocyph\ReqShield\Contracts\Rule;

class StrongPassword implements Rule
{
    public function passes(mixed $value, string $field, array $data): bool
    {
        return strlen($value) >= 12
            && preg_match('/[A-Z]/', $value)
            && preg_match('/[a-z]/', $value)
            && preg_match('/[0-9]/', $value)
            && preg_match('/[^A-Za-z0-9]/', $value);
    }

    public function message(string $field): string
    {
        return "The {$field} must be at least 12 characters with uppercase, lowercase, number, and special character.";
    }

    public function cost(): int { return 20; }
    public function isBatchable(): bool { return false; }
}

// Usage
$validator = Validator::make([
    'password' => ['required', new StrongPassword()],
]);
```

### Database Validation

[](#database-validation)

Validate against your database:

```
use Infocyph\ReqShield\Validator;
use Infocyph\ReqShield\Contracts\DatabaseProvider;

// Implement your database provider
class MyDatabaseProvider implements DatabaseProvider
{
    // Implement required methods...
}

$db = new MyDatabaseProvider();

$validator = Validator::make([
    'email' => 'required|email|unique:users,email',
    'category_id' => 'required|exists:categories,id',
], $db);
```

**Benefits:**

- 🚀 **Automatic batching** - Multiple checks become one query
- 🎯 **Update support** - `unique:users,email,5` ignores ID 5
- 🧾 **Soft-delete aware unique** - `unique:users,email,,id,false,deleted_at`

### Schema Export / Introspection

[](#schema-export--introspection)

```
$jsonSchema = $validator->exportSchema('json_schema');
$openApiShape = $validator->exportSchema('openapi');
$introspection = $validator->exportSchema('introspection');
```

### Stop on First Error

[](#stop-on-first-error)

For maximum performance, stop all validation on first error:

```
$validator = Validator::make($rules)
    ->setStopOnFirstError(true);

// Stops immediately when any field fails
$result = $validator->validate($data);
```

---

⚡ Performance
-------------

[](#-performance)

ReqShield is built for speed:

### 1. **Cost-Based Rule Sorting**

[](#1-cost-based-rule-sorting)

Rules automatically execute in order of complexity:

- **Cheap** (&lt; 50): Type checks, empty checks
- **Medium** (50-99): String operations, regex
- **Expensive** (100+): Database queries, API calls

### 2. **Intelligent Batching**

[](#2-intelligent-batching)

Database rules are automatically batched:

```
// 3 separate rules...
'user_id' => 'exists:users,id',
'email' => 'unique:users,email',
'category_id' => 'exists:categories,id',

// ...become just 2 queries (50x faster!)
// - One batch for exists checks
// - One batch for unique checks
```

### 3. **Fail-Fast Execution**

[](#3-fail-fast-execution)

Stops validating a field on first rule failure:

```
'email' => 'required|email|max:255'
// If empty → fails on 'required', skips 'email' and 'max:255'
```

### 4. **Zero Overhead for Simple Cases**

[](#4-zero-overhead-for-simple-cases)

Nested validation only activates if you use dot notation. No performance cost for simple flat arrays.

---

📄 License
---------

[](#-license)

ReqShield is open-sourced software licensed under the [MIT license](LICENSE).

---

🌟 Show Your Support
-------------------

[](#-show-your-support)

If you find ReqShield helpful, please consider giving it a ⭐️ on GitHub!

---

**Made with ❤️ for the PHP community**

[Documentation](https://docs.infocyph.com/projects/reqshield) • [Report Bug](https://github.com/infocyph/reqshield/issues) • [Request Feature](https://github.com/infocyph/reqshield/issues)

###  Health Score

47

—

FairBetter than 94% of packages

Maintenance90

Actively maintained with recent releases

Popularity21

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity56

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~72 days

Total

3

Last Release

51d ago

Major Versions

1.0 → 2.02026-03-21

### Community

Maintainers

![](https://www.gravatar.com/avatar/33b750b84ab22f2038ef9b90ee48f2fcdaab6b5698e9f956a89a152466200b63?d=identicon)[abmmhasan](/maintainers/abmmhasan)

---

Top Contributors

[![abmmhasan](https://avatars.githubusercontent.com/u/7711128?v=4)](https://github.com/abmmhasan "abmmhasan (52 commits)")

---

Tags

httprequestpsr-7schemavalidatorvalidationsecurityrulesinputsanitization

###  Code Quality

TestsPest

Static AnalysisRector

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/infocyph-reqshield/health.svg)

```
[![Health](https://phpackages.com/badges/infocyph-reqshield/health.svg)](https://phpackages.com/packages/infocyph-reqshield)
```

###  Alternatives

[psr/http-factory

PSR-17: Common interfaces for PSR-7 HTTP message factories

1.9k692.9M1.9k](/packages/psr-http-factory)[fig/http-message-util

Utility classes and constants for use with PSR-7 (psr/http-message)

39489.0M274](/packages/fig-http-message-util)[psr/http-server-handler

Common interface for HTTP server-side request handler

177101.3M921](/packages/psr-http-server-handler)[pdeans/http

PSR-7 cURL HTTP client with support for PSR-17 HTTP factories.

1466.2k3](/packages/pdeans-http)[middlewares/csp

Middleware to add the Content-Security-Policy header to the response

1720.6k](/packages/middlewares-csp)[chillerlan/php-httpinterface

A PSR-7/17/18 http message/client implementation

1417.1k5](/packages/chillerlan-php-httpinterface)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
