PHPackages                             adeptoas/sniff-array - 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. adeptoas/sniff-array

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

adeptoas/sniff-array
====================

A tool for checking array specification conformity

1.7.1(6y ago)1171proprietaryPHPPHP &gt;=7.0.0CI failing

Since Aug 15Pushed 6y ago6 watchersCompare

[ Source](https://github.com/adeptoas/sniff-array)[ Packagist](https://packagist.org/packages/adeptoas/sniff-array)[ RSS](/packages/adeptoas-sniff-array/feed)WikiDiscussions master Synced 4w ago

READMEChangelogDependencies (2)Versions (16)Used By (0)

SniffArray
==========

[](#sniffarray)

This is a lightweight library to check if a given array conforms to a certain specification

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

[](#installation)

Add this to `composer.json`:

```
"require": {
	"adeptoas/sniff-array": "^1.0.0"
}
```

Make sure to merge your `require`-blocks!

Usage
-----

[](#usage)

### ArraySniffer

[](#arraysniffer)

```
__construct(array $spec, bool $throw = false)
```

Initialize an ArraySniffer with the given `spec`. Error handling can be specified via `throw`, else every sniff will simply return `false`.

```
sniff(array $array): bool
```

Start checking `array` for conformity in respect to the current `ArraySniffer` instance's specification.

```
static arrayConformsTo(array $spec, array $data, bool $throw = false): bool
```

Check if `array` conforms to `spec`. This does the same as calling `sniff` on an `ArraySniffer` instance, but is mainly for one-time-only checks

### SplSniffer

[](#splsniffer)

This library provides several sniffers for primitive / SPL types in PHP. They are mainly needed for internal verification purposes, but you can use them as stand-alone verification sniffers if you want to.

```
static forType(string $type): SplSniffer
```

Return a subclass of `SplSniffer` suitable for checking conformity to `type`.

```
sniff(mixed $val, bool $isStrict = false): bool
```

Check if `val` conforms to the specification implied by the current `SplSniffer` instance's type. `isStrict` specifies if certain edge cases should be deemed valid or not (see below for further explanation)

Specification
-------------

[](#specification)

### Base types

[](#base-types)

The basic type identifications delivered with this library are

- string
- int
- number
- bool
- mixed
- array
- object

Some common aliases are also implemented:

- boolean =&gt; bool
- integer =&gt; int
- numeric =&gt; number
- any =&gt; mixed
- empty =&gt; null
- class =&gt; object

Strict specifications are denoted by the type followed by an exclamation sign `!` and narrow down the possible accepted values. In particular:

- string! doesn't accept the empty string `''`
- int! doesn't accept `0`
- number! doesn't accept `0` or `NAN`
- array! doesn't accept empty arrays `[]`
- object! doesn't accept stdClass objects with 0 fields `new stdClass()`
- mixed! doesn't accept arbitrary arrays, only pure primitives

`array` as primitive specification simply denotes any arbitrary array of whatever form, while an explicitly specified nested array specification demands exact matches

### Array specifications

[](#array-specifications)

Any array specification is itself arranged as an associative array.

```
[
    'key'       =>  'string',
    'otherKey'  =>  'int'
]
```

for example is a valid specification for

```
[
    'key'       =>  'value',
    'otherKey'  =>  42
]
```

Specifications can of course be nested.

```
[
    'key'   =>  [
        'first'     =>  'number',
        'second'    =>  'bool'
    ]
]
```

matches for example

```
[
    'key'   =>  [
        'first'     =>  INF,
        'second'    =>  false
    ]
]
```

but (obviously) not

```
[
    'key'   =>  'someString'
]
```

Specification keys can be appended by some RegExp-like features to expand matching functionality, namely:

- `{a,b}` for minimum a and maximum b matches
    - `{,b}` for zero to b matches
    - `{a,}` for a to INF matches
- `+` for one or more matches (equal to `{1,}`)
- `*` for zero or more matches (equal to `{0,}`)
- `?` for an optional match (equal to `{0,1}`)

Keys that allow for 0 matches by use of this RegExp typeset can either be explicitly set to `null` or implicitly dropped.

These RegExp rules can of course also be applied to nested array specification structures.

```
[
    'key'       =>  'string',
    'optional?' =>  'int',
    'any*'      =>  [
        'foo'   =>  'bool',
        'bar'   =>  [
            'one+'      =>  'number!',
            'two{3,5}'  =>  'number!'
        ]
    ]
]
```

matches

```
[
    'key'       =>  'value',
    'optional'  =>  0,
    'any'       =>  [
        [
            'foo'   =>  true,
            'bar'   =>  [
               'one'   =>  123,
               'two'   =>  [456, 789, 321, 654]
            ]
        ], [
            'foo'   =>  false,
            'bar'   =>  [
               'one'   =>  [3.141592, 6.283185],
               'two'   =>  [1.414213, 2.718281, 1.618033]
            ]
        ]
    ]
]
```

as well as

```
[
    'key'       =>  'value',
    'any'       =>  [
        'foo'   =>  true,
        'bar'   =>  [
            'one'   =>  123,
            'two'   =>  [1.1, 2, 3.3, 4, 5.5]
        ]
    ]
]
```

Multiple types can be joined by using the bar `|` sign. This does not infer with any of the other type rules.

```
[
    'key'       =>  'string!|bool',
    'otherKey'  =>  'int|array'
]
```

is a valid specification for

```
[
    'key'       =>  'element',
    'otherKey'  =>  123
]
```

as well as

```
[
    'key'       =>  true,
    'otherKey'  =>  123
]
```

and

```
[
    'key'       =>  false,
    'otherKey'  =>  ['foo', 'bar']
]
```

Arrays that are sequential at root level can be checked for specification match by using the key `__root`. This can be especially useful for bulk mode handling a given specification

```
[
    '__root+'   =>  [
        'foo'       =>  'bool',
        'bar?'      =>  'int'
    ]
]
```

matches

```
[
    [
        'foo'   =>  'true',
        'bar'   =>  0
    ], [
        'foo'   =>  'true'
    ], [
        'foo'   =>  'false',
        'bar'   =>  42
    ]
]
```

Colon notation
--------------

[](#colon-notation)

Some Sniffers, particularly `StringSniffer`, `ObjectSniffer` and `MixedArraySniffer`, support specifying additional sniff data via the usage of `::`

This colon "operator" supports multiple repeated arguments. The effect of an argument is specified by the respective Sniffer class.

For `StringSniffer`, the colon data can be used to specify a matching regular expression (RegExp). The conformity to this RegExp will be checked in addition to the usual check by using `preg_match` as specified in the PHP standard library

```
[
    'foo*'   =>  'string::^[A-Z][a-z]*$'
]
```

matches

```
[
    'foo'   =>  ['Hello', 'World']
]
```

but not

```
[
    'foo'   =>  ['eHlo', 'World', '!']
]
```

Please note that the RegExp will automatically be wrapped in convenient PCRE bounds, (i.e. //) if not wrapped already

For `ObjectSniffer`, the colon data can be used to specify instance class names. They can be fully namespaced, but standard "short name" checks will also be performed.

```
[
    'object'   =>  'class::MyClass'
]
```

matches

```
[
    'object'   =>  new MyClass()
]
```

but neither

```
[
    'object'   =>  new MyOtherClass()
]
```

nor

```
[
    'object'   =>  new stdClass()
]
```

Please also note that multiple classes can be specified using the same colon `::` operator in a repeated fashion

```
[
    'object'   =>  'class::MyClass::MyOtherClass'
]
```

accounts for both

```
[
    'object'   =>  new MyClass()
]
```

and

```
[
    'object'   =>  new MyOtherClass()
]
```

For `MixedArraySniffer`, the colon data can be used to specify whether an associative or a sequential array is desired.

```
[
    'values'   =>  'array::sequential'
]
```

matches

```
[
    'values'    =>  [1, 2, 'one', 'two', true, false]
]
```

but not

```
[
    'values'    =>  [
        'key'   =>  'value'
    ]
]
```

whereas the specification

```
[
    'dict'   =>  'array::associative'
]
```

matches

```
[
    'dict'  =>  [
        'one'   =>  1,
        'two'   =>  2
    ]
]
```

but not the `values` example from above. Common aliases `seq` for `sequential` and `assoc` for `associative` are installed for convenience, so that

```
[
    'members'   =>  'array::seq',
    'relations' =>  'array::assoc'
]
```

is a valid specification. More than one specified array type will be discarded and sniffed as `false` or throw an exception, respectively.

Examples
--------

[](#examples)

Examples will be added to the `Examples/` directory once I come up with meaningful examples that don't involve confidential data from my dayjob.

###  Health Score

30

—

LowBetter than 62% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity12

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity66

Established project with proven stability

 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 ~83 days

Recently: every ~181 days

Total

14

Last Release

2526d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/11876893?v=4)[Visma Meglerfront AS](/maintainers/visma-meglerfront)[@visma-meglerfront](https://github.com/visma-meglerfront)

---

Top Contributors

[![karimdjemai](https://avatars.githubusercontent.com/u/8942592?v=4)](https://github.com/karimdjemai "karimdjemai (7 commits)")

###  Code Quality

TestsPHPUnit

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/adeptoas-sniff-array/health.svg)

```
[![Health](https://phpackages.com/badges/adeptoas-sniff-array/health.svg)](https://phpackages.com/packages/adeptoas-sniff-array)
```

###  Alternatives

[chaoswey/taiwan-id-validator

台灣身分證、統一編號驗證

319.9k](/packages/chaoswey-taiwan-id-validator)

PHPackages © 2026

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