PHPackages                             helixdigital-io/laravel-hyrule - 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. helixdigital-io/laravel-hyrule

AbandonedArchivedLibrary

helixdigital-io/laravel-hyrule
==============================

Fluent API for building validation rules in Laravel

v3.0.2(2y ago)03.5kApache-2.0PHPPHP &gt;=8.1

Since Jan 18Pushed 2y agoCompare

[ Source](https://github.com/helixdigital-io/laravel-hyrule)[ Packagist](https://packagist.org/packages/helixdigital-io/laravel-hyrule)[ RSS](/packages/helixdigital-io-laravel-hyrule/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (2)Dependencies (5)Versions (3)Used By (0)

Laravel Hyrule
--------------

[](#laravel-hyrule)

[![](https://github.com/square/laravel-hyrule/actions/workflows/php.yml/badge.svg)](https://github.com/square/laravel-hyrule/actions/workflows/php.yml/badge.svg)

Hyrule provides an object-oriented, fluent API for building validation rules for use w/ Laravel's Validation component. This unlocks patterns that make it easier to define set of rules to enforce complex, nested data structures that is typical in API development.

**Why:**

Defining validation rules in Laravel involves manually building arrays. As business logic evolves and validation rules become more complex, those arrays grow in size, and building them also becomes more complex. Before long, you find yourself *manipulating* arrays: adding or removing rules based on conditions, refactor segments to be re-used, etc. and over time, this pattern can feel really clunky. It doesn't take a lot to make managing validation rule definitions feel like it's getting out of control. This library aims to fix that by offers a better API that helps you for the long-term:

- Fluent API that allows you to define rules ergonomically e.g. add conditionals with ease, no more error-prone array manipulations.
- Composable: Simplifies rule-building logic that can be reused multiple times, at multiple nesting levels. No more passing down &amp; reconstructing dot-notated prefixes.
- Strictness means less surprises: Promote enforcement of data-types, and reject unknown fields by default.

Installation
------------

[](#installation)

```
composer require square/laravel-hyrule:^2.0
```

> For PHP 7.4 support, install the `1.*` versions. See [1.x README](https://github.com/square/laravel-hyrule/blob/1.x/README.md)

### Setup

[](#setup)

1.) If you do not have [package discovery](https://laravel.com/docs/9.x/packages#package-discovery) enabled, you will have to manually register the service provider:

```
// config/app.php

return [
    // ...
    'providers' => [
       // ...
       Square\Hyrule\HyruleServiceProvider::class,
       // etc.
     ],
];
```

2.) Publish the config:

```
php artisan vendor:publish --provider="Square\Hyrule\HyruleServiceProvider"
```

> Using the service provider &amp; the default config will allow your app to use [`StrictValidator`](./docs/strict-validator.md).

API Basics
----------

[](#api-basics)

Initializing a rule-builder and adding your first field:

```
// Initialize a new builder: it will help you build up your validation rule-set.
$builder = Hyrule::create();

// Describe your expected input:
// It needs the field name *and* the data-type.
// This creates a *Node* that you can then attach rules to:
$builder->string('first_name')
    ->required() // Attach rules. This one marks the field as required.
    ->max(255); // ...and this one says it cannot be greater than 255 chars in length.
```

Fleshing out the rest of your fields &amp; their rules:

```
$builder
    ->string('first_name')
        ->required()
        ->max(255)
        ->end() // Tell the builder you are done w/ this field...
    ->string('last_name') // ...so you can start a new one!
        ->required()
        ->max(255)
        ->end()
    ->integer('age') // ...This field is an integer.
        ->required()
        ->min(21)
        ->max(60)
        ->end();

$rules = $builder->build();

// $rules:
[
    '' => ['required', 'array:first_name,last_name,age'],
    'first_name' => ['string', 'required', 'max:255'],
    'last_name' => ['string', 'required', 'max:255'],
    'age' => ['integer', 'required', 'min:21', 'max:60'],
]
```

Start validating!

```
// Compile into an array Illuminate\Validation\Validator understands.
$rules = $builder->build();

// Use it e.g.
$validator = Validator::make($data, $rules);

// ...or
$request->validate($rules);

// etc.
```

Fields API
----------

[](#fields-api)

Hyrule forces you to define the expected data-type for each field. It supports all ranges of types, from scalar types to non-scalar types.

### Scalar Types

[](#scalar-types)

Adding scalar fields are as easy as:

```
$builder->string('product_name');
$builder->integer('quantity');
$builder->float('rating');
$builder->numeric('display_price')
$builder->boolean('on_sale');
```

### Non-Scalar Types

[](#non-scalar-types)

No matter how deep and complex your validation rules go, you can use the same set of APIs:

#### Objects

[](#objects)

Use `->object(...)` to start defining nested fields e.g.

```
$builder
    // "nutritional_facts" is a required field w/ a bunch of nested fields.
    ->object('nutritional_facts')
        ->required()
        // Describe the fields:
        ->integer('servings_per_container')
            ->required()
            ->min(1)
            ->end()
        ->string('serving_size')
            ->required()
            ->min(1)
            ->max(30)
            ->end()
        // "fat", a nested field, has a bunch of nested fields, too.
        ->object('fat')
            ->integer('saturated_fat_grams')->end()
            ->integer('saturated_fat_percent')
                ->max(100)
                ->end();
            ->end();
```

##### Unknown fields

[](#unknown-fields)

By default, Hyrule helps you build robust &amp; secure applications by only allowing fields you explicitly defined via the Fields API. This is specifically designed to help you be intentional w/ what you expect from your data. For example, this is another mechanism by which your API can further sanitize user input.

If you expect a field to come through, the library would still require you to specify the data-type. But you don't have to specify other rules:

```
Hyrule::create()
    ->string('name')
      ->end()
    // etc.
```

If you'd like to allow unknown fields through, use this method on the appropriate node(s):

```
Hyrule::create()
  ->allowUnknownProperties() // object('data')
    ->allowUnknownProperties() // array()`:

```
// Defines an array field named "tags"...
$builder
    ->array('tags')
        // Array length must be between 1-10 elements long:
        ->min(1)
        ->max(10)
        // ...and each element (i.e. a tag) must be a string between 3-100 chars in length.
        ->each('string')
            ->min('3')
            ->max('100');
        // etc.
```

As you can see in this example, Hyrule promotes strictness even for what goes in arays.

#### Arrays of objects

[](#arrays-of-objects)

Just define it like any other array field, and use the exact same API to define the nested fields:

```
$builder
    // Required "skus" must be between 1-10 items.
    ->array('skus')
        ->required()
        ->min(1)
        ->max(10)
        // Each SKU in the array are objects of their own:
        ->each('object')
            // Each SKU has these fields:
            ->string('name')
                ->required()
                ->max(255)
                ->end()
            ->integer('quantity')
                ->min(0)
                ->end()
            // etc.
```

### File Uploads

[](#file-uploads)

As of 2.3, Hyrule supports specifying rules for file uploads:

```
$builder
    ->file('attachment')
        ->required()
        ->mime('image', 'video', 'text')
        ->end()
    // etc.
```

See the following detailed guides on how to validate file uploads by file-type (MIME type), dimensions, etc.

- [File Upload Validation - Images](./docs/file-upload-validation-images.md)
- [File Upload Validation - Other MIME Types](./docs/file-upload-validation-mime-types.md)

Rules API
---------

[](#rules-api)

First let's talk about what happens when you use the Fields API described above. When you define a field, a *node* is created &amp; returned by the builder. You can then use the Rules API to add validation rules on a node.

##### Basic Example

[](#basic-example)

```
// Adding built-in validation rules in Laravel
$builder
    ->string('foobar') // Returns a `StringNode` for the "foobar" field.
    ->required() // Adds the "required" validation rule.
    // Supports rules that accepts parameters like:
    ->min(1) // Adds "min:1"
    ->max(255) // Adds "max:1"
    ->requiredIf('vehicle_type', 'car') // Adds "required_if:vehicle_type,car"

    // Supports rules that access multiple parameters like:
    ->in('A', 'B', 'C') // Adds "in:A,B,C"
    // etc.
```

##### Custom Rules Support

[](#custom-rules-support)

This library helps you *build* validation rule definitions &amp; does not limit you from using custom rules that doesn't come w/ Laravel:

```
$builder
    ->string('foobar')
        // Converts camel-case to snake-case notation:
        ->barBaz('olives', 'on', 'pizza') // Adds "bar_baz:olives,on,pizza"

        // Supports raw rule definitions:
        ->rule('required_without:another_field')

        // ... as well as custom Rule objects:
        ->rule(new MyCustomRule());
```

### What's up with `->end()`?

[](#whats-up-with--end)

Once you understand that `Square\Hyrule\Builder` manages a tree of nodes and that the Fields APIs return child nodes, all you have to know is that `->end()` returns the *parent* of the node, and it is the fluent way of traversing back up the tree:

```
$builder = Hyrule::create() // The root
    ->string('name')
        ->required()
        ->end() // Brings us back to $builder, the root node

    // New field on root:
    ->object('characteristics')
        ->required()
        ->string('eye_color')
            ->in(...EyeColors::all())
            ->end() // Back to "characteristics"
        ->numeric('height_cm')
            ->end() // Back to "characteristics"
        ->with(...)
    ->end() // Back to $builder, the root node.

    // Another field on root:
    ->array('siblings')
        ->max(10)
        ->each('object') // Starts the "*" ObjectNode
            ->string('name')
            ->end() // Back to the "*" ObjectNode
        ->end() // Back to "siblings"
    ->end() // Back to $builder, the root node.

    // etc.
```

If you are not a fan of this, you can use the [Fields-With API](./docs/fields-with.md).

Advanced Topics
---------------

[](#advanced-topics)

- [Fields-With API](./docs/fields-with.md)
- [Apply rules on entire data itself with **`StrictValidator`**](./docs/strict-validator.md)
- [Reusable builder functions with **`->with(...)`**](./docs/builder-functions-with.md)
- **Built-in helper builder functions**
    - [**`Hyrule::if(...)`**](./docs/hyrule-if.md)
    - [**`Hyrule::requiredIf(...)`**](./docs/hyrule-required-if.md)
- [Path Expressions with **`Hyrule::pathExp()`**](./docs/path-expressions.md)
- [Custom validation for shape of an object](./docs/custom-properties-rule.md)
- [Static analysis w/ PHPStan](./docs/static-analysis-phpstan.md)

###  Health Score

27

—

LowBetter than 49% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity16

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 79.3% 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 ~55 days

Total

2

Last Release

791d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/cb808569841214f1b6b59dca08b367015cdfbcf9826397f20db1efd3439e71bd?d=identicon)[xHeaven](/maintainers/xHeaven)

---

Top Contributors

[![bezhermoso](https://avatars.githubusercontent.com/u/1437428?v=4)](https://github.com/bezhermoso "bezhermoso (23 commits)")[![xHeaven](https://avatars.githubusercontent.com/u/14284867?v=4)](https://github.com/xHeaven "xHeaven (3 commits)")[![peter279k](https://avatars.githubusercontent.com/u/9021747?v=4)](https://github.com/peter279k "peter279k (2 commits)")[![hungthai1401](https://avatars.githubusercontent.com/u/22017922?v=4)](https://github.com/hungthai1401 "hungthai1401 (1 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/helixdigital-io-laravel-hyrule/health.svg)

```
[![Health](https://phpackages.com/badges/helixdigital-io-laravel-hyrule/health.svg)](https://phpackages.com/packages/helixdigital-io-laravel-hyrule)
```

###  Alternatives

[laravel/ui

Laravel UI utilities and presets.

2.7k134.9M601](/packages/laravel-ui)[spatie/laravel-honeypot

Preventing spam submitted through forms

1.6k6.0M60](/packages/spatie-laravel-honeypot)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

71510.9M66](/packages/laravel-mcp)[watson/validating

Eloquent model validating trait.

9723.3M47](/packages/watson-validating)[proengsoft/laravel-jsvalidation

Validate forms transparently with Javascript reusing your Laravel Validation Rules, Messages, and FormRequest

1.1k2.3M49](/packages/proengsoft-laravel-jsvalidation)[yajra/laravel-oci8

Oracle DB driver for Laravel via OCI8

8703.0M17](/packages/yajra-laravel-oci8)

PHPackages © 2026

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