Почему PHP еще далеко то строгой типизации
NikolasSumrakВсем привет.
С выходом php 7.1 мы стараемся активно использовать strict types, да и довольно удобно зачастую указывать типы входных параметров и результата. Довольно местами даже код улучшается, согласитесь, теперь не напишешь вот такой метод, принимающий всё подряд:
class A {
public function foo($param)
{
if ($param instanceof Bar) {
$param = $param->getId();
}
if (is_string($param)) {
$param = $this->someService->getIdByCode($param);
}
// some logic
}
}
А вот так уже выглядит метод со строгим указанием типов:
class A {
public function foo(int $param)
{
// some logic
}
}
И вот тут нас подстерегают коварные подводные камни языка, который еще не всегда готов работать со strict_types.
К примеру у нас есть такой класс:
declare(strict_types=1);
class B {
private $storage = [];
public function setUserRating(string $username, int $rating): void
{
$this->storage[$username] = $rating;
}
public function getUserRating(string $username): ?int
{
return $this->storage[$username] ?? null;
}
public function getAllUsernames(): array
{
return array_keys($this->storage);
}
}
На первый взгляд все отлично, все типы указаны, что тут еще может сломаться?
Давайте рассмотрим вариант, где username состоит только из цифр. Скажем, 12345.
Мы вызываем метод setUserRating, передавая значения в строгом соответствии с типами:
$b = new B;
$b->setUserRating('12345', 33);
А затем дальше где-то в коде используем метод getAllUsernames()
function hello(string $username): string
{
return 'Hello, ' . $username;
};
foreach ($b->getAllUsernames() as $username) {
echo hello($username);
}
И, BOOM! Получаем Fatal error: Uncaught TypeError: Argument 1 passed to hello() must be of the type string, integer given
Что же пошло не так? Все дело в приведении типов языка. Упростив вышесказанное, получим:
$string = '12345'; $array = [$string => 1]; var_dump(array_keys($array));
который выведет нам
array(1) {
[0] => int(12345)
}
т.е. строка '12345' при использовании ее ключом массива, автоматически была приведена к int.
Будьте бдительны при работе с strict types!