What I try to do with this small experiment is to make something similar to Generics, but in PHP, that does not use docblocks for it, nor monomorphization. It does use eval() to create the new named class that extends the core Collection object, and this does not work well with any IDE, but if that does not stop you, then try it out. This is meant more of a fun concept test than an actual production ready package.
Needs:
- PHP >= 8.1
- Composer
composer require thakladd/phenerics
For all types the value gotten from gettype will be used, except it the type is an object, then the result of get_class will be used(unless the type you want in the collection is "object").
The collection object returned is a wrapper for the array, but works as an array because it implements Iterator, ArrayAccess, and Countable.
When building an Collection you have to use the function called arrayOf where the argument is the type. The function returns an empty Collection for that type called ArrayOfType, and you can all that object in order to fill it with an array of that type, and the Collection will do the checks, and throw and exception if there is a mismatch in type.
On a sidenote, I'm a bit on the fence on calling it ArrayOfType, but there is really no good alternative as how I would like to call it(Array<Type>), is not possible. I was considering Array«Type» but those characters are not too accessible on the keyboard. Alternative could be Array_Type but I don't like the snake-camel casing of it. A simple ArrayType could work as well, even if it does not look well with scalar types in PHP like Arrayinteger even if class names are case insensitive, mixing small i here and big I there is not ideal.
Here is an example with a simple array of integers.
//Note the type hint here
function printIntList(ArrayOfInteger $list) {
print_r($list->getList());
}
//Type hint comes from here
$array = arrayOf('integer')([1, 2, 3, 4, 5]);
printIntList($array); //Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 )
print_r($array[1]); //2
$array[] = 6;
print_r($array[5]); //6
print_r($array->get(2)); //3
foreach ($array as $key => $value) {
echo $key . ': ' . $value . ', '; //0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6,
}
And here one with objects.
class Test {
public function __construct(public string $x = '') {}
}
function printTestList(ArrayOfTest $list) {
print_r($list->getList());
}
$arrayOfTest = arrayOf('Test')([new Test('Hello'), new Test('On'), new Test('You')]);
$arrayOfTest->add(3, new Test('You'));
$arrayOfTest[] = new Test('Old');
$arrayOfTest['assoc'] = new Test('Glue');
printTestList($arrayOfTest); //Array ( [0] => Test Object ( [x] => Hello ) [1] => Test Object ( [x] => On ) [2] => Test Object ( [x] => You ) [3] => Test Object ( [x] => You ) [4] => Test Object ( [x] => Old ) [assoc] => Test Object ( [x] => Glue ) )