PHPackages                             horde/constraint - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. horde/constraint

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

horde/constraint
================

Modern constraint library with PHP 8.1+ type safety

v3.0.0(2w ago)14.2k↑41.3%31BSD-2-ClausePHPPHP ^8.1

Since Jan 8Pushed 2w ago5 watchersCompare

[ Source](https://github.com/horde/Constraint)[ Packagist](https://packagist.org/packages/horde/constraint)[ Docs](https://www.horde.org/libraries/Horde_Constraint)[ RSS](/packages/horde-constraint/feed)WikiDiscussions FRAMEWORK\_6\_0 Synced 2d ago

READMEChangelog (3)Dependencies (1)Versions (13)Used By (1)

Horde\_Constraint
=================

[](#horde_constraint)

Modern constraint library for evaluating values against rules.

[![Build Status](https://github.com/horde/Constraint/workflows/CI/badge.svg)](https://github.com/horde/Constraint/actions)

Overview
--------

[](#overview)

Horde\_Constraint provides a flexible system for building and evaluating constraints (rules) that determine whether values satisfy certain conditions. It's useful for validation, filtering, and conditional logic.

**Dual-Stack API:**

- **PSR-4 Modern API** (`Horde\Constraint\*`) - PHP 8.1+ with full type safety
- **PSR-0 Legacy API** (`Horde_Constraint_*`) - Backward compatible

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

[](#installation)

```
composer require horde/constraint
```

Quick Start
-----------

[](#quick-start)

### Modern API (Recommended)

[](#modern-api-recommended)

```
use Horde\Constraint\AllOf;
use Horde\Constraint\IsEqual;
use Horde\Constraint\PregMatch;
use Horde\Constraint\Not;
use Horde\Constraint\IsNull;

// Simple constraint
$constraint = new IsEqual('test');
$constraint->evaluate('test');  // true
$constraint->evaluate('other'); // false

// Compound constraints (AND)
$allOf = new AllOf(
    new IsEqual('admin'),
    new PregMatch('/^[a-z]+$/')
);
$allOf->evaluate('admin'); // true

// Compound constraints (OR)
$anyOf = new AnyOf(
    new IsEqual('admin'),
    new IsEqual('moderator')
);
$anyOf->evaluate('admin'); // true

// Negation
$notNull = new Not(new IsNull());
$notNull->evaluate('value'); // true
$notNull->evaluate(null);    // false
```

### Legacy API

[](#legacy-api)

```
$constraint = new Horde_Constraint_IsEqual('test');
$constraint->evaluate('test'); // true
```

Available Constraints
---------------------

[](#available-constraints)

### Logical Constraints

[](#logical-constraints)

**AllOf** - All constraints must pass (AND logic)

```
$constraint = new AllOf(
    new IsEqual('test'),
    new AlwaysTrue()
);
```

**AnyOf** - Any constraint must pass (OR logic)

```
$constraint = new AnyOf(
    new IsEqual('foo'),
    new IsEqual('bar')
);
```

**Not** - Negates another constraint

```
$constraint = new Not(new IsEqual('forbidden'));
```

### Comparison Constraints

[](#comparison-constraints)

**IsEqual** - Checks equality (loose comparison)

```
$constraint = new IsEqual(123);
$constraint->evaluate('123'); // true (loose comparison)
```

**IsInstanceOf** - Checks if value is instance of a class

```
$constraint = new IsInstanceOf(stdClass::class);
$constraint->evaluate(new stdClass()); // true
```

**IsNull** - Checks if value is null

```
$constraint = new IsNull();
$constraint->evaluate(null); // true
```

### String Constraints

[](#string-constraints)

**PregMatch** - Matches against PCRE regex

```
$constraint = new PregMatch('/^\d{3}-\d{4}$/');
$constraint->evaluate('555-1234'); // true
```

### Constant Constraints

[](#constant-constraints)

**AlwaysTrue** - Always returns true

```
$constraint = new AlwaysTrue();
```

**AlwaysFalse** - Always returns false

```
$constraint = new AlwaysFalse();
```

Usage Examples
--------------

[](#usage-examples)

### Building Complex Rules

[](#building-complex-rules)

```
use Horde\Constraint\{AllOf, AnyOf, Not, IsEqual, PregMatch, IsNull};

// User must be admin OR moderator, AND account must be active
$rule = new AllOf(
    new AnyOf(
        new IsEqual('admin'),
        new IsEqual('moderator')
    ),
    new IsEqual('active')
);

// Validate
$role = 'admin';
$status = 'active';
$isValid = $rule->evaluate($role) && $rule->evaluate($status);
```

### Fluent Constraint Building

[](#fluent-constraint-building)

```
$constraint = new AllOf(
    new IsEqual('value1'),
    new IsEqual('value2')
);

// Add more constraints dynamically
$constraint->addConstraint(new IsEqual('value3'));

// Chaining
$constraint
    ->addConstraint(new IsEqual('value4'))
    ->addConstraint(new IsEqual('value5'));
```

### Filtering with Constraints

[](#filtering-with-constraints)

```
$isValidEmail = new PregMatch('/^[^@]+@[^@]+\.[^@]+$/');

$emails = ['valid@example.com', 'invalid', 'also@valid.com'];
$validEmails = array_filter($emails, fn($email) => $isValidEmail->evaluate($email));
// Result: ['valid@example.com', 'also@valid.com']
```

Architecture
------------

[](#architecture)

### Interface

[](#interface)

All constraints implement:

```
interface Constraint
{
    public function evaluate(mixed $value): bool;
}
```

### Compound Constraints

[](#compound-constraints)

`CompoundConstraint` is the base for constraints that contain other constraints:

- Accepts variadic constructor: `new AllOf(...$constraints)`
- Supports fluent `addConstraint()` for dynamic building
- Automatically flattens nested constraints of the same type

```
$inner = new AllOf(new IsEqual(1), new IsEqual(2));
$outer = new AllOf(new IsEqual(3), $inner);
// Result: 3 constraints total (flattened), not 2 with nesting
```

Migration from PSR-0
--------------------

[](#migration-from-psr-0)

### For Library Users

[](#for-library-users)

**No changes required** - PSR-0 API remains fully functional.

### For New Code (Recommended)

[](#for-new-code-recommended)

Use the modern PSR-4 API:

```
// Before (PSR-0)
use Horde_Constraint_And;
use Horde_Constraint_PregMatch;

$constraint = new Horde_Constraint_And(
    new Horde_Constraint_PregMatch('/pattern/')
);

// After (PSR-4 - recommended)
use Horde\Constraint\AllOf;
use Horde\Constraint\PregMatch;

$constraint = new AllOf(
    new PregMatch('/pattern/')
);
```

### Class Mapping

[](#class-mapping)

PSR-0PSR-4 (Modern)PSR-4 (BC Alias)`Horde_Constraint``Horde\Constraint\Constraint`-`Horde_Constraint_And``Horde\Constraint\AllOf``AndCoupler` (deprecated)`Horde_Constraint_Or``Horde\Constraint\AnyOf``OrCoupler` (deprecated)`Horde_Constraint_Coupler``Horde\Constraint\CompoundConstraint``Coupler` (deprecated)`Horde_Constraint_AlwaysTrue``Horde\Constraint\AlwaysTrue`-`Horde_Constraint_AlwaysFalse``Horde\Constraint\AlwaysFalse`-`Horde_Constraint_IsEqual``Horde\Constraint\IsEqual`-`Horde_Constraint_IsInstanceOf``Horde\Constraint\IsInstanceOf`-`Horde_Constraint_Null``Horde\Constraint\IsNull`-`Horde_Constraint_Not``Horde\Constraint\Not`-`Horde_Constraint_PregMatch``Horde\Constraint\PregMatch`-System Requirements
-------------------

[](#system-requirements)

- **PHP ^8.1** (PSR-4 API)
- **PHP ^7.4** (PSR-0 API, legacy)

Testing
-------

[](#testing)

```
# Run PSR-4 tests
vendor/bin/phpunit --testsuite=psr4

# Run with coverage
vendor/bin/phpunit --testsuite=psr4 --coverage-html coverage
```

**Test Coverage:** 40 tests, 68 assertions

Contributing
------------

[](#contributing)

Contributions are welcome! Please:

1. Follow PER-1 coding style for new code
2. Add tests for new constraints
3. Use Conventional Commits format
4. Ensure all tests pass on PHP 8.1+

Changelog
---------

[](#changelog)

See [doc/changelog.yml](doc/changelog.yml) for version history.

License
-------

[](#license)

BSD-2-Clause - see [LICENSE](LICENSE) for details.

Links
-----

[](#links)

- **Homepage**: [https://www.horde.org/libraries/Horde\_Constraint](https://www.horde.org/libraries/Horde_Constraint)
- **GitHub**:
- **Issues**:
- **Packagist**:

Support
-------

[](#support)

- **Mailing List**:
- **GitHub Issues**:

Credits
-------

[](#credits)

- **Original Author**: James Pepin
- **Lead**: Chuck Hagenbuch
- **Copyright**: 2009-2026 Horde LLC
- **License**: BSD-2-Clause

###  Health Score

60

—

FairBetter than 98% of packages

Maintenance96

Actively maintained with recent releases

Popularity27

Limited adoption so far

Community26

Small or concentrated contributor base

Maturity79

Established project with proven stability

 Bus Factor1

Top contributor holds 72.4% 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 ~522 days

Recently: every ~480 days

Total

9

Last Release

19d ago

Major Versions

2.0.3 → 3.0.0alpha22021-02-24

PHP version history (5 changes)2.0.2PHP &gt;=5.3.0,&lt;=6.0.0alpha1

2.0.3PHP &gt;=5.3.0,&lt;=8.0.0alpha1

3.0.0alpha2PHP ^7

v3.0.0alpha4PHP ^7.4 || ^8 || ^9

v3.0.0alpha8PHP ^8.1

### Community

Maintainers

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

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

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

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

![](https://www.gravatar.com/avatar/816e2b926f25f8cd2939054c7a7173011b4303d690e25ab61bf33cf8c7cf71ae?d=identicon)[tdannhauer](/maintainers/tdannhauer)

---

Top Contributors

[![yunosh](https://avatars.githubusercontent.com/u/379318?v=4)](https://github.com/yunosh "yunosh (84 commits)")[![ralflang](https://avatars.githubusercontent.com/u/646976?v=4)](https://github.com/ralflang "ralflang (27 commits)")[![slusarz](https://avatars.githubusercontent.com/u/381003?v=4)](https://github.com/slusarz "slusarz (3 commits)")[![mrubinsk](https://avatars.githubusercontent.com/u/66822?v=4)](https://github.com/mrubinsk "mrubinsk (1 commits)")[![wrobel](https://avatars.githubusercontent.com/u/10232?v=4)](https://github.com/wrobel "wrobel (1 commits)")

---

Tags

logicconditional

### Embed Badge

![Health badge](/badges/horde-constraint/health.svg)

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

###  Alternatives

[digital-creative/conditional-container

Provides an easy way to conditionally show and hide fields in your Nova resources.

114606.7k4](/packages/digital-creative-conditional-container)[unclecheese/display-logic

Allows assignment of conditions for display and hide of specific form fields based on client side behavior.

771.1M114](/packages/unclecheese-display-logic)[izi-dev/nova-conditional-field

Conditional Field

1624.2k](/packages/izi-dev-nova-conditional-field)

PHPackages © 2026

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