zheltikov/php-type-assert

2.5.1 2021-11-02 09:34 UTC

This package is auto-updated.

Last update: 2024-11-29 06:29:13 UTC


README

A type checking/assertion library for PHP, for more compact and secure code.

Installation

As this is a Composer package, you can install it via:

$ composer require zheltikov/php-type-assert

Usage

This library exposes three functions in the \Zheltikov\TypeAssert namespace:

  • is_(mixed, string): bool
  • as_(mixed, string): mixed
  • null_as_(mixed, string): mixed|null

Example

You may use these functions as follows:

<?php

require_once(__DIR__ . '/../vendor/autoload.php');

use Zheltikov\TypeAssert\{is_, as_, null_as_};

// Using `is_()` to check types
is_(1, 'int');        // true
is_('foo', 'int');    // false
is_(1, 'num');        // true
is_(1.5, 'num');      // true
is_('foo', 'num');    // false
is_('mykey', '?arraykey');  // true
is_('bar', '!num');    // true
is_('X', 'char');    // true

// Enforcing types with `as_()`
as_(1, 'int');        // 1
as_('foo', 'int');    // TypeAssertionException
as_(123, '?num');     // 123
as_('bar', '?num');   // TypeAssertionException

// Get `null` if the type does not match with `null_as_()`
null_as_(1, 'int');        // 1
null_as_('foo', 'int');    // null
null_as_(123, '?num');     // 123
null_as_('bar', '?num');   // null

// As you can see performing type checks with these functions is much more
// compact that doing it with `if`s
// For example, instead of...

if (is_int($value) || is_float($value)) {
    // do something
}

// ...use...

if (is_($value, 'num')) {
    // do something
}

// ...or even...

as_($value, 'num');
// do something

Below comes a simple explanation for each function:

is_(mixed, string): bool

Parameters:

  • mixed $value
  • string $type

Checks whether the value in $value has the type specified in $type, and returns a boolean result.

as_(mixed, string): mixed

Parameters:

  • mixed $value
  • string $expected

Performs the same checks as is_. However, it throws TypeAssertionException if the value has a different type. If the type matches, it returns the original value.

null_as_(mixed, string): mixed|null

Parameters:

  • mixed $value
  • string $expected

Similar to as_, but which returns null if the type does not match.

Supported types and type interpretation

Here comes a list of the supported types and how they are checked internally:

TODO

  • Support for built-in PHP types
  • Support for null and nonnull
  • Support for empty and nonempty
  • Support for mixed and void
  • Support for num
  • Support for arraykey
  • Support for nullable types
  • Support for negated types
  • Support for classname, interfacename and traitname
  • Support for char
  • Support for Stringish: any string-like value
  • Support for custom classnames
  • Support for true and false
  • Support for positive, nonpositive and notpositive
  • Support for negative, nonnegative and notnegative
  • Support for tuples. For example: tuple(int, ?DateTime, bool)
  • Support for closed shapes. For example: shape('id' => int, 'name' => string)
  • Support for open shapes. For example: shape('id' => int, 'name' => string, ...)
  • Support for optional shape fields. For example: shape('id' => int, ?'name' => string)
  • Support for enums:
    • Check by enum type
    • Check by enum field name
  • Support for array generics
    • By value. For example: array<User>
    • By key and value. For example: array<string, int>
  • Support for unions. For example: int|string|null
  • Support for intersections. For example: Exception&Throwable
  • Modularity, ability to define custom checker functions and types
  • Memoize some checker functions
  • Support for type alias definitions
  • Support for type precedence checking definition
  • Support for comments
  • Support for format strings (like for sprintf and sscanf)
  • Support for regular expressions
  • Support for named parameters
  • Support for open tuples: tuple(int, ...), tuple(..., int), tuple(int, ..., int)
  • Support for error (type mismatch) reporting, for humans :)
  • Support for callable types:
    • Support for fixed-count parameters: (function(string, int): array<string, int>)
    • Support for variable-count parameters: (function(string, ...): int)
  • Support for raw integers
  • Support for raw floats
  • Support for shape integer keys
  • The function as_ should convert (cast) the value, rather than checking it. Use some (extendable) converter class.

Performance

You may ask about the performance impact of this parsing process on the overall request. You will be surprised hearing that the performance of the parser included in this library is actually pretty good.

Some tests were made, in which the following type string was being parsed:

shape(
    'id' => int & positive,
    'name' => string,
    'price' => float & positive,
    'score' => null | (int & positive),
    'description' => string,
    'photo_id' => int & positive,
    'category_id' => int & positive
)

This test was performed on PHP v7.4 and PHP v8.0 with JIT compilation enabled, and the result aren't bad at all!:

Note: these performance tests were made at commit d9fedd23..., therefore they may not be accurate for the latest library version.