Зарегистрируйтесь, чтобы продолжить обучение

Описание типов Основы PHP

В этом уроке мы поближе познакомимся с типами данных и обсудим нюансы работы с ними.

Когда мы пишем на PHP, то не особо задумываемся над типами данных. Мы просто пишем код и ожидаем, что данные будут соответствовать нашим ожиданиям:

<?php

function sayHelloTo($name)
{
    print_r("Hello, {$name}");
}

Функция выше ожидает на вход строку. Это видно по тому, как используется переменная $name. А что, если мы ошибемся и передадим массив? Давайте попробуем:

<?php

// В функцию передается не то, что ожидается:
sayHelloTo([]);
// PHP Notice:  Array to string conversion

Код отработает, но результат не будет соответствовать нашим ожиданиям. Ничего страшного в таком поведении нет — это просто цена за использование динамической типизации.

В тех местах, где входной тип особенно важен, можно добавить соответствующую проверку и генерировать исключение, если переданы неверные данные. По крайней мере так делали раньше, до введения в язык механизма type hinting.

Type Hinting — это механизм, который позволяет явно указывать типы параметров. Интерпретатор использует их и применяет исключение в тех ситуациях, когда тип не соответствует ожидаемому. Так работает в большинстве языков, где присутствует этот механизм.

В PHP используется слабая типизация, поэтому здесь все чуть сложнее. Можно жестко указать тип int, но это не значит, что интерпретатор начнет ругаться на все остальное. Он выполнит автоматическое приведение и спокойно обработает и логический, и строковый тип данных.

Чтобы объявить тип аргумента, необходимо перед его именем добавить имя требуемого типа:

<?php

// Тип int говорит, что ожидается число
function sayHelloTo(int $name)
{
    print_r("Hello, {$name}");
}

// Все, что может быть приведено к указанному типу, будет считаться подходящим
sayHelloTo(false); // Hello, 0
sayHelloTo('1'); // Hello, 1

Попробуем в качестве типа аргумента передать строку string:

<?php

function sayHelloTo(string $name)
{
    print_r("Hello, {$name}");
}

sayHelloTo([]);
// PHP Fatal error:  Uncaught TypeError: Argument 1 passed to sayHelloTo() must be of the type string, array given

Теперь ошибка совсем другая — нам явно говорят, что типы не сошлись. Увидеть и исправить подобную ошибку уже значительно легче. Рассмотрим еще один пример с несколькими параметрами:

<?php

function get(string $text, int $index, $default = null)
{
    $length = strlen($text);
    return ($index >= 0) && ($index < $length)  ? $text[$index] : $default;
}

get('hi', 3, 8); // 8

get('ho', 'hey');
// PHP Fatal error:  Uncaught TypeError: Argument 2 passed to get() must be of the type integer, string given

Обратите внимание на отсутствие типа у $default. Значение по умолчанию может быть абсолютно любым, поэтому тип не указывается.

Null не похож на другие типы данных и ведет себя особым образом. Дело в том, что типы данных в PHP не являются nullable — то есть они не допускают значение Null.

Представим, что мы ждем на вход значение определенного типа — например, строку. В PHP строка не может иметь значение Null. Но это ограничение можно обойти. Можно указать значение, по умолчанию равное Null, и тогда указанный тип становится nullable — появится возможность передавать Null снаружи.

Посмотрим, как это выглядит в коде:

Не nullable:

<?php

function printStr(string $value)
{
    echo $value;
}
printStr(null);
// PHP Fatal error:  Uncaught TypeError: Argument 1 passed to printStr() must be of the type string, null given

Nullable:

<?php

function printStr(string $value = null)
{
   echo $value;
}
printStr(null);

Начиная с версии PHP 7.2, в языке появилась возможность указывать тип не только для входящих параметров, но и для возврата функции. Оно записывается через двоеточие после закрывающей скобки:

<?php

function sum(int $a, int $b): int
{
    return $a + $b;
}

Если мы ошибемся в теле функции выше и вернем строку, то интерпретатор скажет об этом:

TypeError: Return value of sum() must be of the type integer, string returned

Еще функция может ничего не возвращать. Например, если она принимает строку, добавляет в конец восклицательный знак и затем печатает результат на экран:

<?php

function sayItLoud(string $text): void
{
    $loudText = "{$text}!";
    print_r($loudText);
}

Чтобы показать, что функция ничего не возвращает, нужно написать в ее сигнатуре после двоеточия — void.

Строгие типы

В его базовом варианте Type Hinting не очень помогает выявить ошибки типов. Он больше полезен в качестве документации и подсказок в редакторе.

Но в PHP есть специальная директива, включающая режим строгой проверки:

<?php

// Включаем режим строгой проверки
declare(strict_types = 1);

function AddIntAndFloat(int $a, float $b): int
{
    return $a + $b;
}

echo AddIntAndFloat(1.4, '2');
// Fatal error: Uncaught TypeError: Argument 1 passed to AddIntAndFloat() must be of the type int, float given
echo AddIntAndFloat(1, '2');
// Fatal error: Uncaught TypeError: Argument 2 passed to AddIntAndFloat() must be of the type float, string given

В таком варианте не происходит автоматического преобразования типов. PHP выполняет точную проверку и выводит ошибку, если типы не совпали.

Типы значений, допускающие значение NULL

Если поставить знак ? перед названием типа данных, то он помечается как обнуляемый — то есть допускающий значение Null.

Это значит, что значение может быть как указанного типа, так и null. Это работает как для входных параметров, так и для возвращаемых функцией значений:

<?php

function isPersonMrSmith(?string $person): bool
{
    // Тут какая-то логика
}

Запись выше означает, что функция isPersonMrSmith() может принять в качестве параметра строку или null.

Стоит сказать, что null должен быть передан явно — isPersonMrSmith(null). Иначе интерпретатор выдаст ошибку:

isPersonMrSmith();
// Fatal error: Uncaught ArgumentCountError: Too few arguments to function

Посмотрим, как ? работает с типом возвращаемого значения:

<?php

public function getName(string $person): ?string
{
    // Тут какая-то логика
}

Функция getName() принимает переменную $person. Затем функция должна вернуть строку с именем человека. Но иногда строки с именем нет — тогда возвращается null.


Дополнительные материалы

  1. Официальная документация
  2. Строгая типизация
  3. Как включить строгую типизацию в PHP и для чего ее использовать

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
от 25 000 ₸ в месяц
Разработка веб-приложений на Laravel
10 месяцев
с нуля
Старт 26 декабря

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»