Объявления типов
В прошлом уроке функция coffee принимала что угодно. Автомат так не работает: прорезь для монет сделана под монету определённой формы, и пуговицу в неё не просунуть.
У функции без типов такой прорези нет. Функция triple($n) с телом return $n * 3; примет и строку 'five', а ошибка случится уже внутри, на умножении: Unsupported operand types: string * int. По такому сообщению не видно, кто передал строку и откуда она взялась.
Поэтому параметрам указывают тип — и PHP проверяет аргумент на входе, при каждом вызове.
Тип параметра и тип результата
Объявление типа — это имя типа перед параметром или после списка параметров. Вот triple с типами:
<?php
function triple(int $n): int
{
return $n * 3;
}
echo triple(4), "\n"; // 12
echo triple('5'), "\n"; // 15
echo triple(2.0), "\n"; // 6Разберём объявление по частям:
int $n— параметр$nпринимает целое число;: intпосле скобок — функция обещает вернуть целое число;- если функция с
: intвернёт строку'abc', вызов закончится ошибкойTypeError.
Обратите внимание на второй и третий вызовы: строка '5' и дробное 2.0 тоже прошли. Без особых настроек PHP работает в режиме приведения: если аргумент можно превратить в нужный тип, PHP превращает его сам.
Что приводится, а что нет
Для параметра int режим приведения действует так:
'5'становится5: в строке записано число;2.0становится2: дробной части нет;2.5становится2, но PHP выводитDeprecated: Implicit conversion from float 2.5 to int loses precision;'five'не становится ничем: числа в строке нет, и вызов бросает ошибку.
echo triple('five'), "\n"; // ✗Fatal error: Uncaught TypeError: triple(): Argument #1 ($n) must be of type int, string givenСообщение называет функцию, номер аргумента и имя параметра, а в конце — что пришло вместо int. Это фатальная ошибка: программа останавливается на этой строке, и ошибка видна там, где передали неверный аргумент.
Режим приведения похож на служащего у автомата: бумажку с цифрой '5' он разменяет на монету 5, а бумажку со словом 'five' вернёт. Только служащий может ошибиться, а правила PHP постоянны: числовая строка проходит всегда, нечисловая — никогда.
Другие типы
Объявить можно любой тип, который вы уже знаете, и несколько новых:
string,float,bool,array— строка, дробное число, логическое значение, массив;mixed— любое значение: так прямо пишут, что подойдёт всё;int|string— объединение типов: подходит значение любого из перечисленных типов;void— только для результата: функция ничего не возвращает и лишь выполняет действие, например печатает.
Есть и never: так помечают функцию, которая никогда не возвращает управление — например, всегда завершается ошибкой.
Тип с null: ?int
Знак вопроса перед типом разрешает ещё и null. Параметр ?string $name принимает строку или null:
function greet(?string $name): string
{
return 'Hi, ' . ($name ?? 'guest');
}
echo greet('Anna'), "\n"; // Hi, Anna
echo greet(null), "\n"; // Hi, guestУ записи ? три правила:
?int— то же самое, чтоint|null: один и тот же тип и одна и та же проверка;?ставится только перед одним типом, поэтому объединение двух типов сnullпишут полностью:int|string|null;- запись
?int|string— ошибка разбора, и файл не запустится.
На собеседовании любят спрашивать, чем ?int отличается от int|null. Ответ: ничем, кроме записи — сокращение ? годится только для одного типа.
Частая ошибка
Считают, что знак вопроса делает параметр необязательным, и вызывают функцию без аргумента:
echo greet(), "\n"; // ✗Fatal error: Uncaught ArgumentCountError: Too few arguments to function greet(), 0 passed and exactly 1 expected?string говорит только о том, какие значения можно передать, а не о том, можно ли не передавать ничего. Необязательным параметр делает значение по умолчанию: ?string $name = null. С ним greet() напечатает Hi, guest.
Главное
int $nи: intобъявляют типы параметра и результата, и PHP проверяет их при каждом вызове.- В режиме приведения
'5'и2.0становятся5и2, а'five'даётTypeError. ?int— то же, чтоint|null, а объединение нескольких типов сnullпишут какint|string|null.- Знак
?не делает параметр необязательным: для этого нужно значение по умолчанию.