PHP Types is a small library/framework aimed to improve and encourage strong typing across your project's codebase, consisting of basic array-types, useful data structures and more, that are not natively available by the language itself.
- 3.1 Primitive types
- 3.2 Primitive arrays
- 3.3 Standard types
- 3.4 Data structures
- 3.5 Type errors
- 3.6
hasAny()andisEmpty()methods - 3.7 The
splicemethod - 3.8 The
lengthproperty - 3.9 Defining custom types
- PHP 8.3.0 or major
- Composer (optional)
- Have an initted Composer project (optional)
Install PHP Types via Composer:
composer require edgaralexanderfr/php-typesor:
You can always download the library as .zip file, decompress it, store it somewhere in your target project and include the autoload.php file from the library's project root:
curl -L -o php-types-master.zip https://github.com/edgaralexanderfr/php-types/archive/refs/heads/master.zip \
&& unzip php-types-master.zip \
&& rm php-types-master.zipor:
You can download the packed .phar version of the library:
mkdir lib \
&& curl -L -o lib/php-types.phar https://github.com/edgaralexanderfr/php-types/raw/master/lib/php-types.phar<?php
declare(strict_types=1);
include 'lib/php-types.phar';
use function PHPTypes\Primitive\string_array;
$message = string_array('Hello', 'world', '!');
print_r($message);PHP Types adds some cool extra types that you can play around with:
<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use function PHPTypes\Primitive\byte;
use function PHPTypes\Primitive\char;
use function PHPTypes\Primitive\uchar;
/** @var byte (Extends from `uint8_t`). */
$byte = byte(255);
/** @var char */
$char = char('c');
/** @var uchar */
$uchar = uchar('A');
/** @var char */
$string = char('Hello!'); // Since `char` can only store a single char, `$string` will be '!' and a PHP Warning will be notified.
echo $byte . PHP_EOL;
echo $char . PHP_EOL;
echo $uchar . PHP_EOL;
echo $string . PHP_EOL;php examples/primitives.php
PHP Warning: Character constant too long for its type
Warning: Character constant too long for its type
255
c
A
!<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use PHPTypes\Primitive\object_t;
use function PHPTypes\Primitive\object_t;
function display(object_t $object): void
{
echo "{$object->name}:" . PHP_EOL;
echo $object->json() . PHP_EOL;
}
$object = object_t([
"name" => "Ford Mustang GT",
"brand" => "Ford",
"category" => "Muscle Car",
"gas" => 0.8,
"engine" => object_t([
"type" => "V8",
"rpm" => 750,
]),
"transmission" => object_t([
"type" => "manual",
"gear" => 1,
"gears" => ["R", "N", "1", "2", "3", "4", "5", "6"],
]),
]);
display($object);php examples/object.php
Ford Mustang GT:
{"name":"Ford Mustang GT","brand":"Ford","category":"Muscle Car","gas":0.8,"engine":{"type":"V8","rpm":750},"transmission":{"type":"manual","gear":1,"gears":["R","N","1","2","3","4","5","6"]}}<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use PHPTypes\Primitive\bool_array;
use function PHPTypes\Primitive\bool_array;
function display(bool_array $array): void
{
foreach ($array as $value) {
echo $value . PHP_EOL;
}
}
$array = bool_array(false, true, false);
display($array);php examples/bool_array.php
1
<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use PHPTypes\Primitive\int_array;
use function PHPTypes\Primitive\int_array;
function display(int_array $array): void
{
foreach ($array as $value) {
echo $value . PHP_EOL;
}
}
$array = int_array(1, 2, 3);
display($array);php examples/int_array.php
1
2
3<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use PHPTypes\Primitive\float_array;
use function PHPTypes\Primitive\float_array;
function display(float_array $array): void
{
foreach ($array as $value) {
echo $value . PHP_EOL;
}
}
$array = float_array(0.1, 2.3, 4.5);
display($array);php examples/float_array.php
0.1
2.3
4.5<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use PHPTypes\Primitive\string_array;
use function PHPTypes\Primitive\string_array;
function display(string_array $array): void
{
foreach ($array as $value) {
echo $value . PHP_EOL;
}
}
$array = string_array('π', 'π', 'π');
display($array);php examples/string_array.php
π
π
π<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use PHPTypes\Primitive\object_array_t;
use function PHPTypes\Primitive\object_t;
use function PHPTypes\Primitive\object_array_t;
function display(object_array_t $array): void
{
foreach ($array as $value) {
print_r($value);
}
}
$array = object_array_t(
object_t([
'id' => 1,
'name' => 'Charles Babbage',
]),
object_t([
'id' => 2,
'name' => 'Alan Turing',
]),
object_t([
'id' => 3,
'name' => 'Edsger Dijkstra',
]),
);
display($array);php examples/object_array.php
PHPTypes\Primitive\object_t Object
(
[id] => 1
[name] => Charles Babbage
)
PHPTypes\Primitive\object_t Object
(
[id] => 2
[name] => Alan Turing
)
PHPTypes\Primitive\object_t Object
(
[id] => 3
[name] => Edsger Dijkstra
)<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use function PHPTypes\Primitive\byte_array;
use function PHPTypes\Primitive\char_array;
use function PHPTypes\Primitive\uchar_array;
$byte_array = byte_array(0, 255, 0, 255);
$char_array = char_array('H', 'e', 'l', 'l', 'o', '!');
$uchar_array = uchar_array('a', 'b', 'c');
var_dump($byte_array);
// Notice how we can print out `char_array`s just like usual strings:
echo $char_array . PHP_EOL;
echo $uchar_array . PHP_EOL;php examples/primitives_arrays.php
object(PHPTypes\Primitive\byte_array)#2 (2) {
["object":protected]=>
array(1) {
["PHPTypes\Primitive\byte"]=>
string(23) "PHPTypes\Primitive\byte"
}
["storage":"ArrayIterator":private]=>
array(4) {
[0]=>
object(PHPTypes\Primitive\byte)#6 (1) {
["val":protected]=>
int(0)
}
[1]=>
object(PHPTypes\Primitive\byte)#7 (1) {
["val":protected]=>
int(255)
}
[2]=>
object(PHPTypes\Primitive\byte)#8 (1) {
["val":protected]=>
int(0)
}
[3]=>
object(PHPTypes\Primitive\byte)#9 (1) {
["val":protected]=>
int(255)
}
}
}
Hello!
abcSimilarly to C, you can make use of the standard types (as you would by including the <stdint.h> standard library) to specify and maintain integer values in certain ranges:
<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use function PHPTypes\Std\int16_t;
use function PHPTypes\Std\int8_t;
use function PHPTypes\Std\uint16_t;
use function PHPTypes\Std\uint8_t;
/** @var int8_t [-128...127] */
$int8_t = int8_t(0);
/** @var uint8_t [0...255] */
$uint8_t = uint8_t(0);
/** @var int16_t [-32768...32767] */
$int16_t = int16_t(0);
/** @var uint16_t [0...65535] */
$uint16_t = uint16_t(0);
// Assigning/accessing values:
$int8_t->value = 256;
$uint8_t->value = -128;
$int16_t->value = 1024;
$uint16_t->value = 2048;
// Displaying new values
// (Notice how the first 2 variables overflow):
echo $int8_t . PHP_EOL;
echo $uint8_t . PHP_EOL;
echo $int16_t . PHP_EOL;
echo $uint16_t . PHP_EOL;php examples/stdint.php
0
128
1024
2048Note: keep in mind that these are only representative values and not actual low-level values where we're not saving space by storing specific bytes per integer.
We can also make use of the size_t data type to store large numbers based on sizes, lengths, etc:
<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use function PHPTypes\Std\size_t;
/** @var size_t [0...PHP_INT_MAX] */
$size_t = size_t(0);
$size_t->value--;
echo $size_t->value . PHP_EOL;php examples/size_t.php
9223372036854775806<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use PHPTypes\Std\Int16Array;
use PHPTypes\Std\Int8Array;
use PHPTypes\Std\UInt16Array;
use PHPTypes\Std\UInt8Array;
use function PHPTypes\Std\int16_array;
use function PHPTypes\Std\int8_array;
use function PHPTypes\Std\size_array;
use function PHPTypes\Std\uint16_array;
use function PHPTypes\Std\uint8_array;
/** @var int8_array */
$int8_array = int8_array(-3, -2, -1);
/** @var uint8_array */
$uint8_array = uint8_array(0, 1, 2);
/** @var int16_array */
$int16_array = int16_array(3, 4, 5);
/** @var uint16_array */
$uint16_array = uint16_array(6, 7, 8);
/** @var size_array */
$size_array = size_array(9, 10, 11);
// or:
/** @var Int8Array */
$int8_array = new Int8Array(-3, -2, -1);
/** @var UInt8Array */
$uint8_array = new UInt8Array(0, 1, 2);
/** @var Int16Array */
$int16_array = new Int16Array(3, 4, 5);
/** @var UInt16Array */
$uint16_array = new UInt16Array(6, 7, 8);<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use PHPTypes\Set\HashSet;
$set = new HashSet();
$set->add(1);
$set->add('two');
$set->add(3);
$set->add(3);
$set->add('two');
$set->add('one');
foreach ($set as $value) {
echo $value . PHP_EOL;
}php examples/hash_set.php
1
two
3
one<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use PHPTypes\Set\IntHashSet;
$set = new IntHashSet();
$set->add(1);
$set->add(2);
$set->add(3);
$set->add(3);
$set->add(2);
$set->add(1);
$set->add(0);
foreach ($set as $value) {
echo $value . PHP_EOL;
}php examples/int_hash_set.php
1
2
3
0<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use PHPTypes\Set\StringHashSet;
$set = new StringHashSet();
$set->add('π');
$set->add('π');
$set->add('π');
$set->add('π');
$set->add('π₯');
foreach ($set as $value) {
echo $value . PHP_EOL;
}php examples/string_hash_set.php
π
π
π
π₯In case you attempt to assign a value with a type different than an array's type, a TypeError is thrown:
<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use function PHPTypes\Primitive\int_array;
$array = int_array(1, 2, 3);
try {
$array[2] = 'π₯';
} catch (TypeError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
$array[] = 'π₯';
} catch (TypeError $e) {
echo $e->getMessage() . PHP_EOL;
}
$array[] = 4;
print_r($array);php examples/type_error.php
Element must be of type integer, string given, called
Element must be of type integer, string given, called
PHPTypes\Primitive\int_array Object
(
[type:protected] => integer
[storage:ArrayIterator:private] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
)Arrays contain useful methods that help to determine whether if they're empty or contain at least 1 element in them:
<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use function PHPTypes\Primitive\object_array;
use function PHPTypes\Primitive\string_array;
$fruits = string_array('π₯');
if ($fruits->hasAny()) {
echo '`$fruits` contains at least 1 element.' . PHP_EOL;
}
$objects = object_array();
if ($objects->isEmpty()) {
echo '`$objects` is an empty array.' . PHP_EOL;
}php examples/has_any_is_empty.php
`$fruits` contains at least 1 element.
`$objects` is an empty array.You can make use of the splice method from arrays the same way you'd use the array_splice function with normal arrays:
<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use function PHPTypes\Primitive\string_array;
$fruits = string_array('π', 'π', 'π₯', 'π');
[$without_mango, $mango] = $fruits->splice(2, 1);
print_r($without_mango);
print_r($mango);php examples/splice.php
PHPTypes\Primitive\string_array Object
(
[type:protected] => string
[storage:ArrayIterator:private] => Array
(
[0] => π
[1] => π
[2] => π
)
)
PHPTypes\Primitive\string_array Object
(
[type:protected] => string
[storage:ArrayIterator:private] => Array
(
[0] => π₯
)
)The splice method returns a multiple, consisting of the resultant array along with the extracted elements respectively.
Similarly to JavaScript/JS, you can make use of the length property to retrieve the count of total elements from a specific array:
<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use PHPTypes\Std\UInt8Array;
$bytes = new UInt8Array(0, 1, 2, 4, 8, 16, 32, 64, 128);
echo $bytes->length . PHP_EOL;php examples/length.php
9To define custom arrays, you can create a new class that extends PHPTypes\ArrayObject and implements a typed constructor for such purpose, e.g:
<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use PHPTypes\ArrayObject;
class User
{
public function __construct(
public readonly int $id,
public readonly string $name,
) {}
}
class UserArray extends ArrayObject
{
public function __construct(User ...$values)
{
parent::__construct($values);
}
}
$users = new UserArray(
new User(1, 'John'),
new User(2, 'Doe'),
);
foreach ($users as $user) {
echo "{$user->id} => {$user->name}" . PHP_EOL;
}php examples/typedef_1.php
1 => John
2 => DoeIt is very common that we may need to define multiple arrays for multiple classes from our project/app, to do so, we can simplify the previous example with the usage of the typedef function, just like this:
<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use PHPTypes\ArrayObject; // Notice the usage of `ArrayObject`
use function PHPTypes\typedef;
class User
{
public function __construct(
public readonly int $id,
public readonly string $name,
) {}
}
typedef('array', 'User', 'UserArray');
/**
* @disregard
* @var ArrayObject|User[]
*/
$users = new UserArray(
new User(1, 'John'),
new User(2, 'Doe'),
);
foreach ($users as $user) {
echo "{$user->id} => {$user->name}" . PHP_EOL;
}php examples/typedef_2.php
1 => John
2 => DoeNotice the usage of the @disregard and @var phpDoc tags to preserve the array treatment per User and recognize the acccess to all its properties and methods by our preferred text editor. We also conjunct the @var type definition with the ArrayObject type to recognize access to methods such as count, hasAny, isEmpty, splice, etc.
In case our User class resides inside a specific namespace, we can specify the full path to the namespace when calling typedef to define the new array inside the same namespace:
<?php
declare(strict_types=1);
namespace App;
include 'vendor/autoload.php';
use PHPTypes\ArrayObject; // Notice the usage of `ArrayObject`
use function PHPTypes\typedef;
class User
{
public function __construct(
public readonly int $id,
public readonly string $name,
) {}
}
typedef('array', 'App\User', 'UserArray');
/**
* @disregard
* @var ArrayObject|User[]
*/
$users = new \App\UserArray(
new \App\User(1, 'John'),
new \App\User(2, 'Doe'),
);
foreach ($users as $user) {
echo "{$user->id} => {$user->name}" . PHP_EOL;
}php examples/typedef_3.php
1 => John
2 => DoeIt is also recommended and a good practice to define custom types in a separate and dedicated file that can be accessed across our app, such as types.php