Search by

dranzd / common-domain-assert

dranzd

Assertions for domain models: webmozart/assert plus a datetime check, behind one class you can extend with your own rules.

Package info

github.com/dranzd/common-domain-assert

pkg:composer/dranzd/common-domain-assert

Statistics

Installs: 5

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.1.0 2026-11-12 13:58 UTC

This package is auto-updated.

Last update: 2026-11-12 14:14:57 UTC


README

CI Latest version PHP version License: MIT

Assertions for domain models. Assertion is webmozart/assert plus a datetime() check, behind a class meant to be extended with the rules of your own domain.

The point of the indirection is ownership. Value objects and entities call Assertion::... instead of a third-party class, so a domain layer has one place to add its own rules and to decide which exception a broken rule throws.

Installation

composer require dranzd/common-domain-assert

Requires PHP 8.3 or newer.

Usage

Every assertion of webmozart/assert is available with the same name, arguments and messages.

use Dranzd\Common\Domain\Assert\Assertion;

final class EmailAddress
{
    public function __construct(private readonly string $value)
    {
        Assertion::email($value, 'Expected an email address, got %s');
        Assertion::maxLength($value, 254);
    }
}

new EmailAddress('ada@example.com'); // passes
new EmailAddress('not-an-email');
// throws Webmozart\Assert\InvalidArgumentException: Expected an email address, got "not-an-email"

Added assertions

Method Passes when
datetime(string $value, string $format, string $message = '') $value is a date or time written in $format
Assertion::datetime('2025-11-02', 'Y-m-d');           // passes
Assertion::datetime('2025-02-29', 'Y-m-d');           // throws: Expected a date with format Y-m-d
Assertion::datetime('2025-11-02', 'Y-m-d H:i:s');     // throws: Expected a date with format Y-m-d H:i:s

Assertion::datetime('tomorrow', 'Y-m-d', 'The delivery date must be written as %s.');
// throws: The delivery date must be written as Y-m-d.

The format is one accepted by DateTime::createFromFormat(). A month, day, hour, minute or second that is out of range is rejected when the format describes a complete date or time: month 13, 29 February outside a leap year, hour 25. The parser is otherwise lenient:

  • it does not insist on zero padding, so 2025-1-5 passes for Y-m-d, and 25-11-02 passes as the year 25;
  • it does not check a weekday name against the date;
  • it does not range-check a partial format, so 31/02 passes for d/m.

A custom message is a sprintf() format that is only evaluated when the assertion fails. Write a literal percent sign as %%.

The nullOr and all prefixes of the base library work for added assertions too:

Assertion::nullOrDatetime(null, 'Y-m-d');                        // passes
Assertion::allDatetime(['2025-11-02', 'tomorrow'], 'Y-m-d');     // throws

Extending it for your domain

Subclass Assertion to add your own rules. Overriding reportInvalidArgument() changes the exception for every assertion, inherited ones included.

use Dranzd\Common\Domain\Assert\Assertion;

final class InvalidOrder extends \DomainException
{
}

final class OrderAssertion extends Assertion
{
    public static function orderNumber(string $value, string $message = ''): void
    {
        self::regex($value, '/^ORD-\d{6}$/D', $message !== '' ? $message : 'Expected an order number, got %s');
    }

    protected static function reportInvalidArgument($message): never
    {
        throw new InvalidOrder($message);
    }
}

OrderAssertion::orderNumber('ORD-000123'); // passes
OrderAssertion::orderNumber('ORD-12');     // throws InvalidOrder: Expected an order number, got "ORD-12"
OrderAssertion::uuid('nope');              // throws InvalidOrder: Value "nope" is not a valid UUID.

Compatibility

This package requires webmozart/assert 1.x (^1.11). The inherited assertions behave exactly as that version documents; this package does not change them. Version 2.x is not supported yet: it changes method signatures that subclasses override and removes the mechanism behind the nullOr and all prefixes for added assertions.

Development

composer install
composer check        # coding standards, static analysis and tests
Command Tool
composer test PHPUnit
composer test:coverage PHPUnit with coverage (needs pcov or Xdebug)
composer phpstan PHPStan, max level
composer cs-check / composer cs-fix PHP_CodeSniffer, PSR-12

A Docker setup is included for running the same commands without a local PHP: make install, then make check.

CI runs the suite on PHP 8.3, 8.4 and 8.5, against the locked and the lowest allowed dependency versions, and requires at least 95% line coverage.

Contributing

See CONTRIBUTING.md. Security issues: see SECURITY.md.

License

MIT