f2/types

Data type declarations with casting, validation and annotations, without DocBlock parsing using pure PHP.

0.1.3 2020-08-12 23:40 UTC

This package is not auto-updated.

Last update: 2024-12-13 18:37:40 UTC


README

Provides a consistent and simple type system with casting and testing of types, using pure PHP and no DocBlock comments.

It works with native PHP types, and can be combined with any other software without interfering.

Types supported

  • Type\BOOL
  • Type\INT
  • Type\FLOAT
  • Type\NUMBER
  • Type\STRING
  • Type\ARR
  • Type\OBJ
  • Type\RESOURCE
  • Type\TYPE
  • Type\CALLBACK
  • Type\CLASSNAME

Use Cases

Metadata about a schema

For example when declaring a database schema:

$user = [
    // 'id' can be either an integer or null
    'id'            => Type\INT + Type\NUL,

    // These fields must be strings, and 'length' is a custom annotation
    'username'      => Type\STRING + [ 'length' => 50 ],
    'first_name'    => Type\STRING + [ 'length' => 50 ],
    'last_name'     => Type\STRING + [ 'length' => 50 ],

    // 'last_login' can be either a string or null
    'last_login'    => Type\STRING + Type\NUL,
];

It is flexible to use for the static context of a class:

use F2\Type;

class User {

    // Types can be combined
    protected $id          = Type\INT + Type\NUL;

    protected $username    = Type\STRING + [
        // Custom annotations must not start with '#'
        'caption' => 'Username',
        'field_type' => 'VARCHAR(20)',

        // Built in annotations for validation and more
        '#required' => true,
        '#validator' => [ self::class, 'usernameValidator' ],
        ];

    protected $notes = Type\STRING + [
        '#required' => false,
        '#maxlen' => 1000,
        ];

    protected $first_name  = Type\STRING + [
        'caption' => 'Given Name',
        'field_type' => 'VARCHAR(30)'

        '#required' => true,
        '#minlen' => 1,
        '#maxlen' => 30,
        '#ctype' => 'alpha',
        ];

    protected $last_name   = Type\STRING + [
        'caption' => 'Family Name',
        '#minlen' => 1,
        '#maxlen' => 30,
        '#ctype' => 'alpha',
        ];
    protected $last_login  = Type\STRING + Type\NUL;

}

You can create a library of centrally managed types and annotations by declaring constants:

use F2\Type;

class CustomTypes {

    const REQUIRED = [
        '#NOT' => [ null, '' ],
        ];

    const EMAIL = Type\STRING + [
        '#for' => 'email'
        ];

    const NAME = Type\STRING + [
        '#minlen' => 1,
        '#maxlen' => 30,
        '#preg' => '|[A-Z][a-zA-Z\ ]+[a-z]|',
        ];

    /**
     * Added here to illustrate the use case
     */
    protected $exampleField = CustomTypes::NAME + CustomTypes::REQUIRED + [
        'caption' => 'Example Field',
        ];

}

Examples

Basic type testing

use F2\Type;

Type::is( 123, Type\INT );       // true
Type::is( 123, Type\FLOAT );     // false
Type::is( 123.0, Type\INT );     // false
Type::is( 123, Type\NUMBER );    // true
Type::is( 123.0, Type\NUMBER );  // true
Type::is( 123, Type\STRING );    // false
Type::is( "123", Type\STRING );  // true

Test a combination of types

Type::is( 123.0, Type\STRING + Type\FLOAT );     // true
Type::is( "123", Type\STRING + Type\FLOAT );     // true

Type::is( 123, Type\STRING + Type\FLOAT );       // false because 123 is an integer

Type casting

use F2\Type;

Type\INT( "123 " );                 // 123
Type\STRING( 123 );                 // "123"
Type\BOOL( 1 );                     // true
Type\BOOL( 0 );                     // false

Type::as( "123", Type\INT )         // 123
Type::as( "123", Type::of(10.0) )   // 123.0

Get type of any value

use F2\Type;

Type::of(10.00)                     // Type\FLOAT

Extensively unit tested

The library is extensively unit tested with more than 700 tests, to detect any incompatabilities between releases, but it has not been used in production yet.

Please let me know if you plan to use it in any framework or application.