Marcin Nabiałek Marcin Nabiałek - 3 months ago 29
PHP Question

Type hinting in PHP 7 - array of objects

Maybe I missed something but is there any option to define that function should have argument or return for example array of User objects?

Consider the following code:

<?php

class User
{
protected $name;

protected $age;

/**
* User constructor.
*
* @param $name
*/
public function __construct(string $name, int $age)
{
$this->name = $name;
$this->age = $age;
}

/**
* @return mixed
*/
public function getName() : string
{
return $this->name;
}

public function getAge() : int
{
return $this->age;
}
}

function findUserByAge(int $age, array $users) : array
{
$result = [];
foreach ($users as $user) {
if ($user->getAge() == $age) {
if ($user->getName() == 'John') {
// complicated code here
$result[] = $user->getName(); // bug
} else {
$result[] = $user;
}
}
}

return $result;
}

$users = [
new User('John', 15),
new User('Daniel', 25),
new User('Michael', 15),
];

$matches = findUserByAge(15, $users);

foreach ($matches as $user) {
echo $user->getName() . ' '.$user->getAge() . "\n";
}


Is there any option in PHP7 to tell function
findUserByAge
should return array of users? I would expect that when type hinting was added it should be possible but I haven't found any info for type hinting for array of objects so probably it's not included in PHP 7. If it's not included, do you have Any clue why it was not included when type hinting was added?

Answer

It's not included.

If it's not included, do you have Any clue why it was not included when type hinting was added?

With the current array implementation, it would require checking all array elements at runtime, because the array itself contains no type information.

It has actually already been proposed for PHP 5.6 but rejected: RFC "arrayof" - interestingly not because of performance issues which turned out to be neglible, but because there was no agreement in how exactly it should be implemented. There was also the objection that it is incomplete without scalar type hints. If you are interested in the whole discussion, read it in the mailing list archive.

IMHO array type hints would provide most benefit together with typed arrays, and I'd love to see them implemented.

So maybe it's about time for a new RFC and to reopen this discussion.


Partial Workaround:

you can type hint variadic arguments and thus write the signature as

function findUserByAge(int $age, User ...$users) : array

Usage:

findUserByAge(15, ...$userInput);

In this call, the argument $userInput will be "unpacked" into single variables, and in the method itself "packed" back into an array $users. Each item is validated to be of type User. $userInput can also be an iterator, it will be converted to an array.

Unfortunately there is no similar workaround for return types, and you can only use it for the last argument.