PHPackages                             marco-fiset/flute - 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. [Validation &amp; Sanitization](/categories/validation)
4. /
5. marco-fiset/flute

ActiveLibrary[Validation &amp; Sanitization](/categories/validation)

marco-fiset/flute
=================

Highly extensible validation framework for PHP

1.0.0(13y ago)1329[4 issues](https://github.com/marco-fiset/flute/issues)DBADPHPPHP &gt;=5.3.0

Since Jan 24Pushed 12y ago3 watchersCompare

[ Source](https://github.com/marco-fiset/flute)[ Packagist](https://packagist.org/packages/marco-fiset/flute)[ Docs](http://github.com/marco-fiset/flute)[ RSS](/packages/marco-fiset-flute/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependenciesVersions (2)Used By (0)

Flute
=====

[](#flute)

### An utterly awesome and easy-to-use, lightweight and highly-extensible fluent validation framework for PHP.

[](#an-utterly-awesome-and-easy-to-use-lightweight-and-highly-extensible-fluent-validation-framework-for-php)

Flute's fluent interface is heavily inspired by [FluentValidation for .NET](https://github.com/JeremySkinner/FluentValidation).

Here is a simple example to get you started :

```
require 'path/to/flute.php';

$validator = new Validator();
$validator->rule_for('first_name')->max_length(100);

$p = new Person('John');
$result = $validator->validate($p);

if ($result->valid()) {
	echo 'Valid!';
}
```

These validation rules are supported out of the box :

- NotNull
- NotEmpty
- Required
- MaxLength
- ... (and many more. You can also **add rules yourself**)

### Creating custom validation rules

[](#creating-custom-validation-rules)

It's very easy to create custom rules, and you don't even have to alter the `Validator` class. Everything is done with magic naming conventions! For example, here is how the NotEmpty rule is built :

```
// The naming is very important here. More on that later.
class NotEmptyRule extends Rule // We must extend the Rule abstract class
{
	//We override the condition function to run our own validation logic
	public function condition($value)
	{
		// The $value variable contains the value we need to validate.
		// For this particular case, it is considered valid if it is
		// not equal to the empty string.
		return $value !== '';
	}
}
```

Once your rule is defined, it must be discoverable by any registered auto-loader in order the make it available to the `Validator` class. Here is how you invoke it :

```
// Create an instance of the validator
$v = new Validator();

$v->rule_for('first_name')->not_empty();
```

See what I did there? No need to add the `not_empty()` function to the validator. Any unknown function invoked on a validator will create a rule named with the following conventions :

- Every word delimited by underscores is capitalized.
- The underscores are removed.
- 'Rule' is appended to the resulting string.

So `not_empty` becomes `NotEmptyRule`. The validator will instantiate a `NotEmptyRule` class and associate it with the property name defined when we called `rule_for`. Easy, huh?

### What if I want to use parameters?

[](#what-if-i-want-to-use-parameters)

Very simple. Here is a brief look at the `MaxLengthRule` implementation.

```
class MaxLengthRule extends Rule
{
	public function condition($value)
	{
		return strlen($value) max_length;
		//W-w-w-wait, what!? Where does max_length come from?
	}
}

$v = new Validator();
$v->rule_for('first_name')->max_length(100);
```

Any parameters passed to the function definition will be registered in the `args` array *in the same order* that they were passed to the validator rule. You can also access args with the magic `__get` method, like I did here with `max_length`. I you were to call `max_length` again, it will send back the same value as the first time it was called. When using multiple arguments, they are handed out in the order they were passed, and each name gets its own argument.

### Extending existing rules

[](#extending-existing-rules)

Your custom rule can extend the behaviour of existing rules. Let's take a look at the `RequiredRule` implementation :

```
class RequiredRule extends Rule
{
	public function extend() {
		return array(
			new NotNullRule(),
			new NotEmptyRule()
		);
	}
}
```

As you can see, the `RequiredRule` is only a combination of the `NotNullRule` and the `NotEmptyRule`. The `extend` function returns an array of instantiated rules which you want to extend. The `condition` function will be called on both rules and combined with a logical `and`. That is, if any of the condition fails, it is considered invalid.

That's it for the moment! Stay tuned for more awesome features!

###  Health Score

26

—

LowBetter than 43% of packages

Maintenance14

Infrequent updates — may be unmaintained

Popularity14

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity58

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

Unknown

Total

1

Last Release

4862d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/d02a21113b47b4e0b79ba1f901cf4d30dee5942c86cf6bab8d066c01f36cea98?d=identicon)[marco-fiset](/maintainers/marco-fiset)

---

Top Contributors

[![marcofiset](https://avatars.githubusercontent.com/u/1094085?v=4)](https://github.com/marcofiset "marcofiset (45 commits)")

---

Tags

validationfluentextensible

### Embed Badge

![Health badge](/badges/marco-fiset-flute/health.svg)

```
[![Health](https://phpackages.com/badges/marco-fiset-flute/health.svg)](https://phpackages.com/packages/marco-fiset-flute)
```

###  Alternatives

[composer/semver

Version comparison library that offers utilities, version constraint parsing and validation.

3.3k489.6M672](/packages/composer-semver)[giggsey/libphonenumber-for-php

A library for parsing, formatting, storing and validating international phone numbers, a PHP Port of Google's libphonenumber.

5.0k148.7M416](/packages/giggsey-libphonenumber-for-php)[respect/validation

The most awesome validation engine ever created for PHP

5.9k37.4M383](/packages/respect-validation)[propaganistas/laravel-phone

Adds phone number functionality to Laravel based on Google's libphonenumber API.

3.0k35.7M107](/packages/propaganistas-laravel-phone)[opis/json-schema

Json Schema Validator for PHP

64736.9M186](/packages/opis-json-schema)[giggsey/libphonenumber-for-php-lite

A lite version of giggsey/libphonenumber-for-php, which is a PHP Port of Google's libphonenumber

8912.9M47](/packages/giggsey-libphonenumber-for-php-lite)

PHPackages © 2026

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