PHPackages                             locomotivemtl/charcoal-validator - 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. locomotivemtl/charcoal-validator

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

locomotivemtl/charcoal-validator
================================

Data validation

17PHPCI failing

Since May 6Pushed 6y ago13 watchersCompare

[ Source](https://github.com/locomotivemtl/charcoal-validator)[ Packagist](https://packagist.org/packages/locomotivemtl/charcoal-validator)[ RSS](/packages/locomotivemtl-charcoal-validator/feed)WikiDiscussions master Synced 3d ago

READMEChangelogDependenciesVersions (1)Used By (0)

Charcoal Validator
==================

[](#charcoal-validator)

Powerful data validation.

Table of content
================

[](#table-of-content)

- [How to install](#how-to-install)
    - [Dependencies](#dependencies)
- [Example usage](#example-usage)
- [The validator](#the-validator)
- [Rules](#rules)
    - [Choice](#choice-rule)
    - [Color](#color-rule)
    - [Date](#date-rule)
    - [Email](#email-rule)
    - [Empty](#empty-rule)
    - [Ip](#ip-rule)
    - [Filesize](#filesize-rule)
    - [Filetype](#filetype-rule)
    - [Length](#length-rule)
    - [Null](#null-rule)
    - [Password](#password-rule)
    - [Phone](#phone-rule)
    - [Regexp](#regexp-rule)
    - [Url](#url-rule)
- [Validation Results](#validation-results)
- [Development](#development)
    - [Development dependencies](#development-dependencies)
    - [Coding Style](#coding-style)
    - [Authors](#authors)
    - [Changelog](#changelog)

How to install
==============

[](#how-to-install)

The preferred (and only supported) way of installing charcoal-rule is with **composer**:

```
composer require locomotivemtl/charcoal-rule
```

Dependencies
------------

[](#dependencies)

- `PHP 7.2+`
- `ext-json`
- For result serialization.
- `ext-mb`
    - For multibytes (unicode) string length validation.
- `ext-fileinfo`
    - For reading file's mimetype information.

Example usage
=============

[](#example-usage)

```
$validator = new Validator([
	new NullRule(),
	new LengthRule([ 'min' => 3, 'max' => 200 ])
],
[
	new LengthRule([ 'max' => 150 ])
]);

$stringToValidate = 'foobar';
$result = $validator($stringToValidate);
echo $result->isValid();
```

The Validator
=============

[](#the-validator)

The validator is the main interface to all validations. Its goal is to link various validators to perform series of validations in a unified way. It also allows to split the validations by level (*error*, *warning* or *info*).

It has a single function, `validate()`, which is also invokable, and returns a `Validation` object.

```
public function __construct(
  array $errorRules,
  array $warningRules,
  array $infoRules
);
public function __invoke($val): Validation;
```

The Validation object
---------------------

[](#the-validation-object)

The `Validation` object is a collection of results (`\Charcoal\Validator\Result`) for each validation levels. It is typically not instantiated directly, but returned from invoking a `Validator` instance.

```
public function results(
    ?string $level=null,
    bool $returnFailures=true,
    bool $returnSkipped=false,
    bool $returnSuccess=false
) : array;
public function isValid(?string $level=null) : bool;
public function isSkipped(): bool;
```

Validator options
-----------------

[](#validator-options)

Validation runners are stateless; all options must be passed directly to the constructor.

The only options available are the different types of rules to use. See the [example](#)

Rules
=====

[](#rules)

Every rule is stateless, all *options* must be passed directly to the constructor.

Every rule have only one public method: `process($val)`, which can also be invoked directly. It always returns a `Result` object.

Result
------

[](#result)

Result holds the result code after processing a rule on.a value. It is typically not instantiated directly, but returned from invoking a `Rule` instance.

```
public function getType(): string;
public function getCode(): string;
public function getMessage(): string;
public function isValid() : bool;
public function isSkipped(): bool;
```

Available rules
---------------

[](#available-rules)

- [Choice](#choice-rule)
- [Color](#color-rule)
- [Date](#date-rule)
- [Email](#email-rule)
- [Empty](#empty-rule)
- [Filesize](#filesize-rule)
- [Filetype](#filetype-rule)
- [Ip](#ip-rule)
- [Length](#length-rule)
- [Null](#null-rule)
- [Password](#password-rule)
- [Phone](#phone-rule)
- [Regexp](#regexp-rule)
- [Url](#url-rule)

Date Validator
--------------

[](#date-validator)

The date validator ensures a value is a date-compatible string or a DateTime object and, optionally, in a specific range between `min` and `max`.

### Options

[](#options)

OptionTypeDefaultDescription**min**`integer``0`The minimum date. If 0, empty or null, then there is no minimal constraint.**max**`integer``0`The maximum date. If 0, empty or null, then there is no maximal constraint.**checkType**`bolean``true`Whether to fail on invalid date type (if true), or skip (if false).### Result messages

[](#result-messages)

CodeDescription**date.failure.min**Failure if the given date is before than than the minimal constraint.**date.failure.max**Failure if the given date is after the maximal constraint.**date.failure.invalid-type**Failure f the given value is not a valid date. (`check_type` is true).**date.skipped.invalid-type**Skipped if the given value is not a valid date. (`check_type` is false).**date.skipped.empty-val**Skipped if the given value is null or empty.**date.success**Success if all validation (min, max, and date type) pass.Email Validator
---------------

[](#email-validator)

The email validator ensures a value is a proper email address.

### Options

[](#options-1)

OptionTypeDefaultDescription**mx**`boolean``false`Additional MX record validation.### Result messages

[](#result-messages-1)

CodeDescription**email.failure.invalid-type**Failure if the given value is not a string or can't be cast to string.**email.failure.invalid-email**Failure if the given string is not a valid email.**email.failure.invalid-mx**Failure if the MX resolution fails.**email.skipped.empty-val**Skipped if the given value is null or empty.**email.success**Success if all validation (type, email and mx, if applicable) pass.Empty Validator
---------------

[](#empty-validator)

The empty validator ensures a value is **not** "empty". In PHP, *empty* means `''`, `[]` (an empty array), `0`, `'0'`, `false` or `null`. Any object instance is not considered empty.

### Options

[](#options-2)

OptionTypeDefaultDescription**require\_empty**`boolean``false`Set to `true` to ensure value **is** empty.### Result Messages

[](#result-messages-2)

CodeDescription**empty.failure.is-empty**Failure if the given value is empty. (`require_empty` is false, default).**empty.failure.is-not-empty**Failure if the given value is not empty (`require_empty` is true).**empty.success.is-empty**Success if the given value is empty. (`require_empty` is true).**empty.success.is-not-empty**Success if the given value is not empty. (`require_empty` is false, default).Length Validator
----------------

[](#length-validator)

The length validator ensures a string (or a *string-object*) is of a certain length.

This validator skips null or empty strings. Use the [Null Validator](#null-rule) or the [Empty Validator](#empty-rule) to check for those cases, if need.

This validator works with unicode by default (using `mb_strlen` for comparison). It can be disabled by setting the `unicode` option to false.

### Options

[](#options-3)

OptionTypeDefaultDescription**min**`integer``0`The minimum length. If 0, do not check.**max**`integer``0`The maximum length. If 0, do not check.**unicode**`boolean``true`Count unicode (multibytes) character as only 1 character.> Using the `unicode` flag uses the `mb_strlen` to calculate strin length. Therefore, the `mb` PHP extension is required.

### Result messages

[](#result-messages-3)

CodeDescription**length.failure.min**Failure if the given value is longer than minimal constraint.**length.failure.max****length.skipped.no-min-max****length.skipped.empty-val****length.skipped.invalid-type****length.success**Null Validator
--------------

[](#null-validator)

The empty validator ensures a value is **not** *null*.

It can also performs the opposite validation (ensuring a value **is** *null*) by setting the `require_null` option to `true`.

### Options

[](#options-4)

OptionTypeDefaultDescription**require\_null**`boolean``false`Set to `true` to ensure value **is** null.### Result messages

[](#result-messages-4)

MessageDescription**null.failure.is-null****null.failure.is-not-null****null.success.is-null****null.success.is-not-null**Pattern Validator
-----------------

[](#pattern-validator)

The pattern validator ensures a string (or a *string-object*) is of a certain length.

### Options

[](#options-5)

OptionTypeDefaultDescription**pattern**`string``''`The regexp.### Messages

[](#messages)

MessageDescription**regexp.failure.no-match****regexp.skipped.no-pattern****regexp.skipped.empty-val****regexp.skipped.invalid-type****regexp.success**Custom Rules
============

[](#custom-rules)

It's very simple to add a custom rule to a Validator constructor. The abstract `\Charcoal\Validator\Rule` can be extended to create custom rule service. Alternatively callback rules are supported as long as they have the following signature:

```
use \Charcoal\Validator\Result;
function(mixed $value) : Result;
```

Here is an example of a callback custom rule:

```
use \Charcoal\Validator\Validator;
use \Charcoal\Validator\NullRule;
use \Charcoal\Validator\Result;

$validator = new Validator([
	new NullRule(),
	function($value) : Result  {
		if (!is_string($value)) {
			 return new Result(
				 Result::TYPE_SKIPPED,
				 'fullstop.skipped.invalid-type',
				 'Value is not a string.'
				);
		}
		if (substr($val, -1) !== '.') {
			return new Result(
				Result::TYPE_FAILURE,
				'fullstop.error.no-fullstop',
				'The sentence does not end with a full stop.'
			);
		} else {
			return new Result(
				Result::TYPE_SUCCESS,
				'fullstop.success.fullstop',
				'The sentence ends with a full stop.'
			);
		}
	}
]);
$validationResult = $validator($val);
$success = $validationResult->isValid();
$results = $validationResult->results(Validator::LEVEL_ERROR);
```

It is also possible to use an instance of `Rule`, which provides some helper functions to generate responses and messages:

```
use \Charcoal\Validator\Validator;
use \Charcoal\Validator\NullRule;
use \Charcoal\Validator\Rule;
use \Charcoal\Validator\Result;

class FullStopRule extends Rule
{
	public function process($val): Result {
		if (!is_string($val)) {
			return $this->skip('fullstop.skipped.invalid-type');
		}
		if (substr($val, -1) !== '.') {
			return $this->failure('fullstop.error.no-fullstop');
		} else {
			return $this->success('fullstop.success.fullstop');
		}

	}

	public function messages(): array
	{
		return [
			'fullstop.skipped.invalid-type' => '',
			'fullstop.error.no-fullstop' => '',
			'fullstop.success.fullstop' => ''
		];
	}
};

$validator = new Validator([
	new NullRule(),
	new FullStopRule()
]);

$validationResult = $validator($val);
$success = $validationResult->isValid();
$results = $validationResult->results(Validator::LEVEL_ERROR);
```

Development
===========

[](#development)

To install the development environment:

```
$ composer install --prefer-source
```

Run tests with

```
$ composer test
```

Development dependencies
------------------------

[](#development-dependencies)

- `phpunit/phpunit`
- `squizlabs/php_codesniffer`
- `satooshi/php-coveralls`

Continuous Integration
----------------------

[](#continuous-integration)

ServiceBadgeDescription[Travis](https://travis-ci.org/locomotivemtl/charcoal-rule)[![Build Status](https://camo.githubusercontent.com/74dbdf2dce96289790d7801f1415a31e3b1be5107e7f885e2a00c1a309255beb/68747470733a2f2f7472617669732d63692e6f72672f6c6f636f6d6f746976656d746c2f63686172636f616c2d72756c652e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/locomotivemtl/charcoal-rule)Runs code sniff check and unit tests. Auto-generates API documentation.[Scrutinizer](https://scrutinizer-ci.com/g/locomotivemtl/charcoal-rule/)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/0217cbebe94f5f0205b2c3c55aded359930e37e399e6d3809a09ccdb6f68716a/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6c6f636f6d6f746976656d746c2f63686172636f616c2d72756c652f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/locomotivemtl/charcoal-rule/?branch=master)Code quality checker. Also validates API documentation quality.[Coveralls](https://coveralls.io/github/locomotivemtl/charcoal-rule)[![Coverage Status](https://camo.githubusercontent.com/0b07aee1997d93e86fc9906ea7c6ec56825655c3763138285b9b2b72cd185bbd/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f6c6f636f6d6f746976656d746c2f63686172636f616c2d72756c652f62616467652e7376673f6272616e63683d6d6173746572)](https://coveralls.io/github/locomotivemtl/charcoal-rule?branch=master)Unit Tests code coverage.[Sensiolabs](https://insight.sensiolabs.com/projects/5c21a1cf-9b21-41c8-82a8-90fbad808a20)[!\[SensioLabsInsight\](https://insight.sensiolabs.com/projects/ /mini.png)](https://insight.sensiolabs.com/projects/5c21a1cf-9b21-41c8-82a8-90fbad808a20)Another code quality checker, focused on PHP.Coding Style
------------

[](#coding-style)

The Charcoal-Validator module follows the Charcoal coding-style:

- [*PSR-4*](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md), autoloading is therefore provided by *Composer*.
- [*PSR-12*](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-12-extended-coding-style-guide.md)
- [*phpDocumentor*](http://phpdoc.org/) comments.
- Read the [phpcs.xml](phpcs.xml) file for all the details on code style.

> Coding style validation / enforcement can be performed with `composer phpcs`. An auto-fixer is also available with `composer phpcbf`.

> This module should also throw no error when running `phpstan analyse --level=max src/ tests/` 👍.

Authors
-------

[](#authors)

- [Locomotive](https://locomotive.ca)

License
=======

[](#license)

**The MIT License (MIT)**

*Copyright © 2016 Locomotive inc.*

> See [Authors](#authors).

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

###  Health Score

18

—

LowBetter than 8% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity6

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity33

Early-stage or recently created project

 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.

### Community

Maintainers

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

---

Top Contributors

[![mducharme](https://avatars.githubusercontent.com/u/12157?v=4)](https://github.com/mducharme "mducharme (15 commits)")

### Embed Badge

![Health badge](/badges/locomotivemtl-charcoal-validator/health.svg)

```
[![Health](https://phpackages.com/badges/locomotivemtl-charcoal-validator/health.svg)](https://phpackages.com/packages/locomotivemtl-charcoal-validator)
```

###  Alternatives

[webmozart/assert

Assertions to validate method input/output with nice error messages.

7.6k894.0M1.2k](/packages/webmozart-assert)[bensampo/laravel-enum

Simple, extensible and powerful enumeration implementation for Laravel.

2.0k15.9M104](/packages/bensampo-laravel-enum)[nette/forms

📝 Nette Forms: generating, validating and processing secure forms in PHP. Handy API, fully customizable, server &amp; client side validation and mature design.

54013.2M450](/packages/nette-forms)[swaggest/json-schema

High definition PHP structures with JSON-schema based validation

48612.5M73](/packages/swaggest-json-schema)[stevebauman/purify

An HTML Purifier / Sanitizer for Laravel

5325.6M19](/packages/stevebauman-purify)[ashallendesign/laravel-config-validator

A package for validating your Laravel app's config.

217905.3k5](/packages/ashallendesign-laravel-config-validator)

PHPackages © 2026

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