PHP has seen many improvements for the last few years, especially adding the type system, which helps us to avoid runtime errors and make the debugging easier. However, the built-in type system in PHP has some missing parts; for example, we cannot have a strictly typed array, which we are going to address this issue here, and how we can solve it.
Problem with arrays
The problem with arrays in PHP is that they don’t support type systems. For example we cannot specify an array to only accept integers.
$array = [];
$array[] = 1;
$array[] = 'first';
$array[] = 'second';
foreach($array as $item){
echo $item;
}
This code works fine, but what if we wanted to add more restrictions over our array?
Before we solve this problem, we need to learn about array collections.
Collections
A collection is a class that lets us work with an array in an object-oriented way which helps us to have more control over arrays.
The easiest way to have a collection is to extends our object from `\ArrayObject` class:
<?phpclass Collection extends \ArrayObject
{
}
Wwe can use the Collection
class as an array:
$collection = new Collection([1,2,3]);
$collection[] = 'first';
$collection[] = 'second';
foreach($collection as $item){
echo $item;
}
Now that we have a collection, we can modify our Collection
class to check the value’s type before we add it to the array:
We can check the given value by overriding the offsetSet
and the append
methods from ArrayObject
class. If the value was not instance of the collectionType
it throws an exception.
Here is how we can use this class:
$collection = new Collection(UserInterface::class);
$collection[] = new User();
$collection[] = new User();
print_r($collection);
The output for this code, as expected, would be an array with two members, but as soon as we try to put a value with other types, we will receive an error:
$collection[] = 'user1';
As you can see, now we are able to specify what types are allowed to add to our arrays. But our Collection
has an issue; it only works if we try to add a class into our collection. What if we wanted to have an array that only accepts int
or float
?
To solve this issue, we need to change our checkType
method in the Collection
class:
protected function checkType($value): bool
{
switch ($this->collectionType) {
case 'int':
return is_int($value);
case 'string':
return is_string($value);
case 'float':
return is_float($value);
default:
return $value instanceof $this->collectionType;
}
}
As you can see, we checked for different types in the checkType
method. To use this class, let’s create another class and call it IntegerCollection
:
Simply, by creating a class and extends it from our Collection
class, and override the contructor, we can have an array that only accepts int
values.
$collection = new InegerCollection();
$collection[] = 1;
$collection[] = 1;
print_r($collection);$collection[] = 'test'; // throws an exception
Summary
By using array collection, we can have more flexibility when working with arrays, especially when we need to have an array with a specific type.