Обнуляемые типы возврата в PHP7

159

PHP 7 вводит декларации возвращаемого типа . Это означает, что теперь я могу указать, что возвращаемое значение - это определенный класс, интерфейс, массив, вызываемый или один из недавно включаемых скалярных типов, как это возможно для параметров функции.

function returnHello(): string {
    return 'hello';
}

Часто случается, что значение присутствует не всегда, и вы можете вернуть либо что-то типа, либо null. Хотя вы можете сделать параметры обнуляемыми, установив их значение по умолчанию null ( DateTime $time = null), похоже, не существует способа сделать это для возвращаемых типов. Это действительно так, или я как-то не понимаю, как это сделать? Они не работают:

function returnHello(): string? {
    return 'hello';
}

function returnHello(): string|null {
    return 'hello';
}
Йерун Де Дау
источник
8
В PHP7 пока не допускаются типы возвращаемых значений, допускающие значения NULL, но есть RFC, который призван решить эту проблему в PHP 7.1 здесь . Правильное обозначение будет тогдаfunction returnString(?string $stringNull) : ?string { return $stringNull;}
Элиас Ван Отегем
1
В итоге я эмулировал обнуляемость, злоупотребляя исключениями в моем приложении. Если вам хорошо и глупо, это может пригодиться: github.com/JeroenDeDauw/OhMyPhp/blob/master/src/…
Йерун Де Дау
Возможно, было бы более разумно использовать Trowableинтерфейс PHP7 (в частности, расширение TypeError)
Элиас Ван Оотегем

Ответы:

258

PHP 7.1 теперь поддерживает типы возвращаемых значений . Первый RFC, с которым я связался, это тот, на который они пошли:

function nullOrString(int $foo) : ?string
{
    return $foo%2 ? "odd" : null;
}

старый ответ:

Так как мой комментарий был фактически ответом на вопрос:

PHP 7 пока не поддерживает nullable-return-типы, но есть RFC для решения этой проблемы, он направлен на PHP 7.1. Если он пройдет, синтаксис будет влиять на все подсказки типа (как возвращаемые типы, так и подсказки типа):

public function returnStringOrNull(?array $optionalArray) : ?string
{
    if ($optionalArray) {
        return implode(', ', $optionalArray);//string returned here
    }
    return null;
}

Есть также конкурирующий RFC для добавления типов объединения, который мог бы делать то же самое, но выглядел бы по-другому:

public function returnStringOrNull(array|null $optionalArray) : string|null
{
    if ($optionalArray) {
        return implode(', ', $optionalArray);//string returned here
    }
    return null;
}

Но сейчас вам нужно написать:

public function returnStringOrNull( array $optionalArray = null)
{
    if ($optionalArray) {
        return implode(', ', $optionalArray);
    }
}

Или просто верните пустую строку, чтобы она соответствовала типу возвращаемого значения, и проверьте ложное значение:

public function returnStringOrNull( array $optionalArray = null) : string
{
    if ($optionalArray) {
        return implode(', ', $optionalArray);
    }
    return '';
}
//call
$string = $x->returnStringOrNull();
if (!$string) {
    $string = $x->returnStringOrNull(range(1, 10));
}
Элиас Ван Отегем
источник
5
PHP 7 won't support nullable return-types just yet, but there's an RFC out to address just that- да, RFC, "только пока". Не поймите меня неправильно - я действительно опытный пользователь PHP, так как до сих пор действительно дурацкий PHP3, без пробелов, но когда я увидел все эти RFC, которые они отвергли за 7, у меня сложилось впечатление просто «WTF ?!». Пользователи видят беспорядок и желают убрать его обратно совместимым способом, и они просто получают «нет». Чистые методы именования беспорядка? Исправленаnull не будучи слишком особенным гражданином? Нет, не нужно Добавить опцию, чтобы сделать все вещи чувствительными к регистру? Нах .. А потом, удивление, что люди меняются.
Марцин Орловский
1
@MarcinOrlowski: Подсказка типа возвращаемого значения, обнуляемого, имеет смысл. Я следил за парой RFC в течение 7, и я согласился по большей части с ними, отвергая многие из них. Изменения, на которых они фокусировались, были не столько в языке, сколько в среде выполнения и компиляторе. Для некоторых RFC, которые были отклонены, стоит прочитать темы обсуждения, чтобы понять, почему они решили не реализовывать эти изменения (например, устарели var). Что жаль, что вместо этого они приняли слишком много хороших (например, оператор космического корабля)
Элиас Ван Отегем
@EliasVanOotegem Типы Nullable теперь поддерживаются должным образом, так как версия 7.1 была выпущена 1 декабря.
Одинокий день
@ lonesomeday: Действительно, добавил ссылку + базовый пример в конец моего ответа
конец Элиас Ван Отегем
ммм иш хороший тип, чтобы обновить этот ответ! то есть тип объединения не поддерживается в PHP 7.1
Dennis
67

Обнуляемые типы доступны в PHP 7.1.

Это пример синтаксиса:

public function getName(): ?string
{
    return $this->name; // name can be null
}

PHP 7.1 теперь GA, и вы можете обновить PHP 7.0 (есть только несколько несовместимых изменений, которые вы должны проверить)

орехи
источник
22
IMO - это шутка, чтобы доставлять декларации типа возврата без реализации «nullable». Типы возврата не могут использоваться до тех пор, пока не будет реализована функция «Nullable».
joonas.fi
2
@ joonas.fi Строго типизированные возвращаемые значения IMO всегда должны быть этого типа, нулевой возврат не сохраняется в этом контракте и должен скорее генерировать исключение, придающее больше смысла причине нулевого значения.
Стив Бузонас
8
@SteveBuzonas, если вы рассматриваете метод getAgeInYears () для объекта, представляющего человека, как бы вы смоделировали человека, который не сообщил нам свой возраст? Вернуть ноль? Вернуть 0? Возвращение null семантически означает «мы не знаем», а 0 семантически означает «человеку 0 лет». Поэтому я бы сказал, что getAgeInYears (): int - лучший дизайн. Бросать исключения должны быть зарезервированы для ... исключительных случаев. Незнание возраста человека в большинстве систем не должно рассматриваться как исключительный случай.
joonas.fi
@ joonas.fi очень верно, и это обычная практика. Тем не менее, ваша реализация теперь должна знать, что это поле можно обнулять и явно обрабатывать соответствующим образом. Который очень хорошо может быть делать x, кроме случаев, когда null, который можно так же легко реализовать с помощью try / catch. Кроме того, если для продолжения выполнения нужно действительно указать значение в этом поле, допускающем значение NULL, исключение, вероятно, является лучшим вариантом.
Стив Бузонас
Я заметил, что этот синтаксис заставляет PHPMD выдавать много ошибок. Надеюсь, они скоро это исправят.
Том Джовитт
0

Работает с любым типом.
Пример:

public function getOpportunity(): ?Opportunity
{
    return $this->opportunity;
}
Байма Бруно
источник